Java 线程池笔记
从执行器到线程池 Pooling is the grouping together of resources (assets, equipment, personnel, effort, etc.) for the purposes of maximizing advantage or minimizing risk to the users. The term is used in finance, computing and equipment management.——wikipedia “池化”思想不仅仅能应用在计算机领域,在金融、设备、人员管理、工作管理等领域也有相关的应用。 在计算机领域中的表现为:统一管理IT资源,包括服务器、存储、和网络资源等等。通过共享资源,使用户在低投入中获益。除去线程池,还有其他比较典型的几种使用策略包括: 内存池(Memory Pooling):预先申请内存,提升申请内存速度,减少内存碎片。 连接池(Connection Pooling):预先申请数据库连接,提升申请连接的速度,降低系统的开销。 实例池(Object Pooling):循...
线程安全与锁优化
版本说明:本文主要基于 JDK 6 ~ JDK 14 的 HotSpot 虚拟机实现。需要注意的是,从 JDK 15 开始,偏向锁已被默认关闭并标记为废弃(JEP 374)。如果你使用的是 JDK 15+,文中关于偏向锁的内容仅作为历史参考。 线程安全 什么是线程安全 “当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。” 相对的线程安全,可以分成五个等级。但在深入讨论线程安全的分类之前,我们需要先理解 Java 内存模型——它是理解线程安全问题的理论基础。 Java 内存模型基础 Java 内存模型(Java Memory Model,JMM)是 Java 语言规范的一部分,定义了多线程程序中共享变量的访问规则。理解 JMM 是理解线程安全问题的基础。 为什么需要内存模型? 现代计算机系统中,CPU 与主内存之间存在巨大的速度差异。为了弥补这一差距,硬件层面引入了多级缓存(L1、L2、L3 Cache)。这带来了一个问...
无锁队列
Java 一读一写(SPSC):Memory Barrier + Volatile 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657/** * Single-Producer Single-Consumer (SPSC) 无锁环形队列。 * * <p>原理说明: * - 仅允许一个线程调用 {@code offer()},一个线程调用 {@code poll()}。 * - 由于没有写竞争,无需 CAS;只需保证写操作对消费者可见。 * - 使用两个 volatile 索引(head/tail)建立 happens-before 关系: * 生产者写入元素 → volatile 写 tail → 消费者 volatile 读 tail → 读取元素。 * - 这本质上利用了 Java 内存模型中的“volatile 写-读”内存屏障(StoreLoad), * ...
Java 并发编程笔记
juc.xmind 写在前面的话 并发编程最早的实践都在操作系统里。 管程 理论和实践之间是有鸿沟的,要弥合这种鸿沟,通常需要我们去学习别人的实践。比如并发的标准设计思想来自于操作系统里的管程(monitor),我们应当学习管程,进而了解标准的并发模型-管理共享变量和线程(并发任务)间通信的基本理论模型。 MESA 模型 JAVA 采用 MESA 模型: 互斥(Mutual Exclusion):通过锁机制保证同一时刻只有一个线程能进入管程内部执行。 同步(Synchronization):利用条件变量(Condition Variable)实现线程间的等待与唤醒。 Signal and Continue: 当线程发出通知(signal/notify)时,它继续持有锁并运行,而被唤醒的线程仅仅是进入就绪队列,并不立即抢占 CPU。 必须使用 while 循环: 由于线程被唤醒后不一定立即执行,当它重新获得锁时,环境条件可能已发生变化,因此必须在一个 while 循环中重新检查等待条件(while (condition) { wait(); })。 为什么用 se...
常见故障整理
手写 sql if 条件的字段为空则不应该拼接条件,是一个很容易被忽略的编程错误。如果线上发生了这个问题,则可能导致数据同步出错。 极度危险的错误 元素内容必须由格式正确的字符数据或标记组成,这通常是因为>``<``>=``<=类的标签没有经过转义。 防止手写 sql 被注入 所有 condition 用()圈起来。单独在 condition 里面拼装。用 and 来连接这些 condition。 在最外围使用随机化的()来包裹整个 where 的条件,防止有人猜到()的层次。 mybatis 的替换难点 #{} 是预编译处理,${} 是直接替换。直接替换会有 sql 注入的风险。 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991...
LLM 代码修改传递指令模板
系统指令 12345678910111213141516171819202122232425你是一个专业的编程助手。在整个对话过程中,你需要随时准备生成一个完整的实现指南(输出为一个md格式的文件),让另一个 LLM 能够在原始文件上重新实现你所做的所有修改。## 核心要求:1. **记录所有修改**:跟踪每一个代码变更、新增功能、配置修改等;除了聊天上下文里的代码变更以外,还要读取当前的 git diff 输出2. **生成传递文档**:当用户要求时,立即生成包含以下内容的 Markdown 文档: - 完整的上下文说明(项目背景、功能需求) - 详细的实现步骤(按顺序列出所有修改) - 准确的代码变更(包含完整的 Git Diff 格式) - 技术细节和注意事项 - 验证方法和测试要点## 文档结构模板:- **概述**:功能描述和业务价值- **项目信息**:仓库、文件路径、相关依赖- **实现步骤**:逐步的修改指导- **代码变更**:完整的 Git Diff 或代码片段- **技术要点**:关键实现细节和最佳实践- **注意事项**:配置要求、依赖...
分布式事务
问题定义 对经典的电商场景而言:下单是个插入操作,扣减金额和库存是个更新操作,操作的模型不同,如果进行分布式的服务拆分,则可能无法在一个本地事务里操作几个模型,涉及跨库事务。 CAP 定义 根据 Eric Brewer 提出的 CAP 理论: Consistency:All Nodes see the same data at the same time。所有节点看到同一份最新数据(线性一致性)。 Availability:Reads and writes always succeed。非故障节点必须在合理时间内响应。 Partition tolerance:System continues to operate despite arbitrary message loss or failure of part of the system。网络分区时系统继续运行。 由此诞生三种设计约束和取舍方向: CA:放弃P,仅适用于单点系统,非分布式,如 MySQL主从同步。 AP:放弃强一致性,保证高可用。Cassandra,DynamoDB。Gossip协议可实现最终一致性。 CP...
系统设计
System Design 总结 面试前你需要了解的16个系统设计知识 《搞定系统设计:面试敲开大厂的门》 从 0 到 100 万用户的扩展 数据库的选择 先把服务器里计算和存储的服务器分离开来。 在如下情况下,可以考虑 NoSQL: 低延迟。 非结构化非关系型。 只需要序列化格式-或者对序列化格式友好。 需要存储海量数据。 《你到底用 NoSQL 来做什么?》 scale up vs scale out 纵向扩展的缺点: 有硬性限制。 没有冗余。 横向扩展对大型应用更合适。 负载均衡器 failover 基于负载均衡器就够了,有了 LB 我们才能装多台服务器。 数据库复制 从换主很容易丢失数据,先要恢复脚本才能实现对数据的合法写和读。 缓存 读写模式 我们常用的缓存策略叫 Cache-Aside Cache,完整介绍在《Caching Strategies and How to Choose the Right One》。 如果是应用自己加在缓存,就是 cache aside;如果缓存自己带有 load 方法-比如 guava 的 loader 实现,则意味着 ...
《编程之美》
序言 下水道井盖为什么是圆的 “下水道井盖是圆的,因为圆形不会掉进井口,而且圆形具有均匀分布压力的优势。” 一个屋子有一个门(门是关闭的)和3盏电灯。屋外有3个开关,分别与这3盏灯相连。你可以随意操纵这些开关,可一旦你将门打开,就不能变换开关了。确定每个开关具体管哪盏灯? 答:将一盏灯开一段时间,再关掉,在剩余2盏灯里随机开一盏,进屋去看,发热的灯对应第一个碰的开关,亮着的灯对应开关开着的开关,灭的灯对应没碰过的开关。 游戏之乐 如何写一个程序让 cpu 占用率保持在 50%? 不要用 if-else 来解决,要把比例转成不同的 worktime。 解法的精确与否其实取决于“多久时间内测度一次已占用的时间”和“睡眠”两类 api 的精度。 基本思路: 先计算一下某个周期内的目标时间: 假设我们使用 1s 为一个完整周期,则这个周期的 50% 为0.5s。 我们就用当前时间 + 0.5s 得到一个真正目标时间,比如当前时间在 15:06秒,目标时间就是15:06.5。如果有毫秒偏差,以此类推。 找一个无限 while 循环,内部只做两件事: 进行一个稍微复杂的数学计算,如开平...
Grokking the System Design
设计一个电梯系统 项目链接 myElevator 思路 1. 这道题考察候选人的什么知识? 面试官不是真的想让候选人造一台电梯,而是想通过这个问题评估候选人的综合能力,主要包括: 需求分析与沟通能力:这是最重要的一点。一个优秀的工程师在动手前,会先问问题,明确需求和边界。直接埋头开始写代码的候选人通常会失分。 面向对象设计 (OOD) 能力:这个问题是考察OOD的绝佳场景。如何将现实世界的实体(电梯、楼层、按钮、乘客)抽象成清晰、低耦合的对象和类? 算法与数据结构:电梯调度策略是整个系统的核心,这直接考察候选人的算法设计能力。如何选择合适的数据结构来存储和处理请求,以实现高效的调度? 状态机建模能力:电梯的运行本身就是一个状态机(静止、上升、下降、开门、关门等)。能否清晰地定义这些状态以及它们之间的转换条件,是衡量逻辑思维严谨性的关键。 并发与同步问题:多部电梯、多个乘客请求,这些都是并发场景。候选人是否能意识到可能存在的竞态条件(Race Condition)和资源同步问题? 系统扩展性 (Scalability):设计是只针对一台电梯,还是一个拥有多台电梯的系统?如何将单...










