资讯详情

2026阿里并发编程全优笔记:从JMM到线程池的实战梳理

📅 2026/9/23 4:18:23 | 华诺云谱 👁 阅读
2026阿里并发编程全优笔记:从JMM到线程池的实战梳理
如果你啃过几本并发编程相关的书也刷过一些技术博客大概率会有和我当时一样的感受每个知识点单独拎出来好像都认识synchronized 知道、volatile 也听说过可一旦要把它们组合起来解决线上问题脑子里的知识立刻变成一团浆糊。我真正把“并发编程”这几个字吃透靠的不是刷了多少篇文章而是把一份体系完整的“阿里并发编程全优笔记2026最新版”从头到尾过了三遍再配合大量自己写的样例代码才慢慢把散落的知识点串成一张网。今天这篇文章就基于这份笔记的框架结合我多年写并发代码的真实经验把并发编程这条主线的核心内容完整梳理一遍。这份笔记不是什么速成鸡汤它更像一张由一线工程师反复打磨出来的并发知识地图覆盖 JMM、锁、并发容器、线程池、异步编排、常见故障排查这些关键节点特别适合三类人看刚接触并发、想建立体系化认知的 Java 后端开发写 CRUD 写腻了、想在技术上往上走一步的工程师以及系统已经出现过并发问题、想系统排查和预防的运维或者全栈同学。接下来我按照笔记的逻辑把每块内容掰开揉碎顺带把我踩过的坑和验证过有效的做法一并写出来。1. 并发编程笔记的整体设计与学习思路1.1 先明确“全优笔记”到底在讲什么网上流传的“阿里并发编程全优笔记”其实是一套被反复整理、多次迭代过的 Java 并发编程学习资料核心源自一线工程师在真实业务场景里的沉淀。2026 最新版相比早年间流传的版本最大的变化是融入了新版 JDK如 JDK 17、JDK 21下的实践差异比如对虚拟线程的铺垫性介绍、对synchronized在现代 JVM 中表现的重新评估以及对 CompletableFuture 异步编排更深入的落地案例。笔记的价值不在于告诉你有多少知识点而在于它对知识点做了分层底层是 Java 内存模型JMM和并发理论中间是锁、并发容器、工具类这些基础设施顶层才是线程池、异步编排、高并发系统设计等实战内容。这种分层方式和人的认知习惯是匹配的先弄清楚底层“为什么”再去看上层“怎么做”才能做到真正理解而不是死记硬背。1.2 并发编程为什么容易学成“夹生饭”我见过不少同学学习了几个月并发依然搞不清楚这样的问题为什么加了volatile变量还是被多线程改乱了为什么HashMap在多线程下会死循环为什么明明用了线程池系统还是被拖垮答案都可以归结到并发编程的三大根源可见性、原子性、有序性。CPU 缓存和主内存之间的一致性需要协议来保证这是可见性问题的来源CPU 为提升效率会乱序执行指令这是有序性问题的来源多线程切换导致一段代码被拆成多条指令交错执行这是原子性问题的来源。要理解这三个问题可以想象一个多人协作的厨房你负责切菜我负责炒菜他负责摆盘。每个人都有自己的小台面CPU 缓存共享一个大冰箱主内存。如果切菜的人把切好的菜放在自己台面上没有及时放到冰箱炒菜的人去冰箱里取就会扑空这是可见性问题如果三个人都觉得自己应该最后摆盘指令顺序就乱了这是有序性问题如果两个人同时去冰箱里取同一条鱼大家都想“先取出鱼再放回去”两个操作交错执行就可能出岔子这是原子性问题。并发编程的一切工具和技巧本质上都是在解决这三个问题。这份笔记的聪明之处是它没有一上来就让你背并发工具类 API而是反复强调 JMM 和“三大问题”这个底层坐标系。当你理解了一切的工具都是为这三大问题服务的再回头看锁、CAS、并发容器思路会顺非常多。2. 核心知识体系拆解JMM、锁、容器、线程池2.1 先从线程生命周期和 JMM 说起笔记中第一条主线是线程本身。Java 里创建线程的方式有很多种Thread、Runnable、Callable、FutureTask、线程池本质上最后都是创建一个Thread对象并调用start()。线程的状态机NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED看着简单但很多线上问题都出在状态转换上比如wait()和notify()使用不当线程就一直卡在 WAITING 状态不干活。JMMJava 内存模型是并行编程的地基。它的核心规定是每个线程有自己的工作内存对应 CPU 缓存线程对共享变量的操作必须先拷贝到工作内存操作完成后再刷回主内存。这就产生了一个危险的空档期——一个线程改了变量还没刷回主内存另一个线程读到的就是旧值。JMM 为了约束这种不确定性定义了 happens-before 规则比如“一个锁的解锁 happens-before 后面对这个锁的加锁”所以同一个锁保护的代码块天然不会被并发破坏“对 volatile 字段的写入 happens-before 后续对该字段的读取”所以volatile能保证可见性但不保证原子性。我一开始不理解为什么volatile不能保证原子性直到用两个线程各执行 10000 次count才发现count根本不是一条指令而是“读取-计算-写回”三步volatile只能保证三步过程中别人改的值对我可见但不能阻止三步之间交错进行。2.2 锁的选择从 synchronized 到 JUC 显式锁锁是解决原子性最直接的武器。Java 里的锁体系很庞大但核心选择无非三个层次。第一层是synchronized这是 JVM 内置锁经过多次优化偏向锁、轻量级锁、重量级锁的升级过程后大多数场景下性能已经不差。笔记里特别提醒很多人对synchronized的印象还停留在“重量级锁”时代实际上 HotSpot 会通过锁消除、锁粗化来优化它在低竞争场景下它甚至比ReentrantLock更轻。第二层是ReentrantLock它提供的功能更丰富可中断等待、公平锁、多个Condition队列、tryLock带超时尝试等。这些能力在解决死锁、实现精细控制时非常有用。比如tryLock(3, TimeUnit.SECONDS)这种写法拿到锁就继续拿不到就放弃或走降级逻辑可以极大降低死锁概率。第三层是读写锁ReentrantReadWriteLock和StampedLock。读多写少的场景用读写锁能把并发度拉高一大截StampedLock则更进一步读操作完全乐观只有在写操作冲突时才升级为悲观锁。选择建议也很简单能用synchronized就不要引入额外复杂度需要超时、可中断、公平性时才用ReentrantLock多读少写用读写锁但写非常少且性能极度敏感时再考虑StampedLock——毕竟它的 API 更容易用出错。2.3 并发容器ConcurrentHashMap 不是万能的笔记中另一个重点模块是并发容器。很多人的第一反应是“并发场景下用 ConcurrentHashMap 就完事了”但这个结论只说对了一半。ConcurrentHashMap在 JDK 1.8 后的实现是用 CAS synchronized锁住桶的头节点锁粒度比 JDK 1.7 的段锁更细并发度更高。但它有几个“不为人知”的细节size()方法返回的是一个估计值不是实时精确值putIfAbsent这种复合操作是原子的但“先查后改”这种业务逻辑依然需要自己保证原子性。除了ConcurrentHashMap笔记还花了不少篇幅讲CopyOnWriteArrayList、BlockingQueue以及并发工具类CountDownLatch、CyclicBarrier、Semaphore。我印象最深的是这三个工具类的语义差异特别容易搞混。CountDownLatch是一次性的倒数门闩适合主线程等一批任务完成CyclicBarrier是可循环使用的屏障适合一批线程互相等待齐头并进比如分片处理数据时每个线程处理完一片后等大家到齐再进入下一轮Semaphore则是信号量限流适合控制同时访问某个资源的线程数比如数据库连接池。我早期写多线程分片处理时用了CountDownLatch下一次循环就发现不能复用换成CyclicBarrier才解决从那次以后我见到这两个类就会下意识地确认一遍业务场景再下手。2.4 线程池参数不是背出来的是算出来的线程池是并发编程从理论走向实战的必经之路也是笔记中最长的一章。ThreadPoolExecutor的七大参数——核心线程数、最大线程数、空闲存活时间、时间单位、工作队列、线程工厂、拒绝策略——每一个都值得仔细研究。执行流程可以简化成一句话任务先提交给核心线程核心线程满了进队列队列满了拉起最大线程数的额外线程连最大线程都拉满以后触发拒绝策略。很多线上事故都是这个流程没理解透导致的比如把队列设置成无界队列最大线程数形同虚设任务无限堆积最终内存溢出让整个应用崩溃。拒绝策略有四种默认实现AbortPolicy抛异常、CallerRunsPolicy让提交任务的线程自己执行、DiscardPolicy直接丢弃、DiscardOldestPolicy丢弃最老的任务。我自己最常用的是CallerRunsPolicy因为它的效果是“牺牲调用者保住任务本身”在流量高峰期天然起到了 feedback 限流的作用而不是简单粗暴地把请求丢掉。3. 必须动手实践的几类并发模型3.1 线程池参数计算的完整示例参数不能拍脑袋定我给一个自己实际用过的场景。假设一个 8 核服务器上部署订单导出服务每个导出任务需要占用 CPU 处理 50ms等待数据库和网络 IO 消耗 150ms一个任务总时长约 200ms。这里遵循一个经验公式IO 密集型的核心线程数 CPU 核数 × (1 IO 等待时间 / CPU 计算时间)。代入数值就是8 × (1 150 / 50) 8 × 4 32所以核心线程数可以设为 32。最大线程数一般设置为核心线程数的 1.5 到 2 倍这里取 48。队列容量怎么定假设系统期望积压的任务最多让用户多等 5 秒那么队列容量 5 秒 × 每秒的峰值任务提交数。如果峰值是每秒 40 个任务队列容量可以设置 200。注意这个公式算完之后还要压测验证因为真实系统的 CPU 消耗和 IO 等待并不是恒定不变的。另外一个容易忽略的参数是threadFactory。一定要给线程池里的线程设置一个有意义的名字前缀比如order-export-thread-。排查线上问题时线程名会直接出现在jstack输出里命名清晰的话一眼就能看出是哪个线程池在忙能节省大量排查时间。3.2 并发容器的选型视角从读写比例出发选容器不是看广告而是看场景的读写比例和一致性要求。读多写少、集合大小不大优先考虑CopyOnWriteArrayList。它读操作不加锁写操作是复制整个数组再替换引用在配置项管理这类场景下非常好用。但你要是用它存储频繁变化的缓存数据会频繁触发数组复制GC 压力剧增。写多读少或者读写压力都很大用ConcurrentHashMap或ConcurrentSkipListMap。需要按 key 排序就用跳表不需要就用哈希表。注意ConcurrentSkipListMap的并发度通常不如ConcurrentHashMap因为跳表操作链路更长。单机场景的并发控制还需要注意一个点ConcurrentHashMap只保证单个方法原子性不保证组合动作原子性。比如“if (map.containsKey(key)) { map.put(key, value) }”在多线程下就是有问题的需要改成computeIfAbsent这类原子方法。这个坑我在做本地缓存时踩过当时数据偶发不一致排查半天才发现是“先判断后写入”这个组合动作出了问题。3.3 异步编排CompletableFuture 替代“回调地狱”高并发系统里异步化是提升吞吐量最直接的手段。早期 Java 用Future做异步但Future的get()是阻塞的业务逻辑一旦复杂就会陷入回调嵌套代码读起来非常痛苦。笔记中花了很大篇幅讲CompletableFuture我认为它最值钱的能力是任务编排。举一个典型的下单场景查询用户信息、校验库存、计算优惠、创建订单、生成支付链接这五个步骤中前三个互不依赖可以并发执行后两个依赖前面结果顺序执行。用CompletableFuture的写法大概是先定义三个异步任务分别查用户信息、校验库存、计算优惠然后用thenCombine把用户信息和库存结果合并再用thenCompose串起后续的创建订单和生成支付链接逻辑。一旦用了这种编排方式接口总耗时就不再是五个步骤的耗时总和而是“最慢的一个并行分支耗时 串行部分耗时”吞吐量提升立竿见影。需要注意两点第一给CompletableFuture显式传入自定义线程池不要用默认的ForkJoinPool.commonPool()因为公共线程池的线程数等于 CPU 核数减一高并发下很容易打满第二异步任务里一定要处理异常分支用exceptionally或者handle兜底否则异常会静默吞掉接口白等半天返回一个奇怪结果。4. 高频故障与排查思路实录4.1 死锁的定位与恢复死锁是并发编程里最经典的故障之一。产生死锁需要四个条件同时满足互斥、持有并等待、不可剥夺、循环等待。我在实际项目中遇到过一个很典型的案例线程 A 持有订单锁后去获取库存锁线程 B 持有库存锁后去获取订单锁两个线程互相等待对方释放谁也跑不动。排查步骤很固定先用jps找到 Java 进程 pid再用jstack pid打印线程栈日志里会直接出现Found one Java-level deadlock并列出参与死锁的线程。解决死锁的办法通常有三类一是调整加锁顺序所有人都按照“先订单后库存”的顺序加锁二是用tryLock加超时拿不到锁就回滚或重试三是缩小锁的范围不要在持锁期间做耗时操作比如不要在锁内调远程接口。4.2 线程池队列积压与线程泄漏线程池最隐蔽的问题不是拒绝策略而是队列积压。现象是请求越来越慢但线程数和 CPU 都很正常因为任务都堵在队列里排队。这种问题的排查路径一般是三步先看监控中线程池活跃线程数和队列大小确认是不是队列持续增长再打印线程栈看线程都在干什么是不是有线程卡在某个 IO 调用上最后追查任务本身的耗时分布看是不是某个下游依赖变慢拖垮了整体。线程泄漏则是另一种折磨。典型场景是业务代码里写了while (true)循环去消费消息循环没有退出条件导致线程池里大量线程永远处于 RUNNABLE 状态线程数缓慢爬升最终触发拒绝策略。还有一种常见泄漏是对ThreadLocal使用不当线程池里的线程是复用的如果往ThreadLocal里存了对象却不清理下一次任务复用线程时会读到上一次任务的脏数据甚至因为强引用一直存在导致内存泄漏。解决方案就是两个用完立刻remove()以及不要用ThreadLocal存大对象。4.3 伪共享一个容易被忽略的性能刺客伪共享是一个比较底层的并发性能问题。CPU 从主内存读数据时并不是按变量逐个读而是按缓存行通常是 64 字节批量读入。如果两个线程修改的是同一缓存行里的不同变量哪怕这两个变量毫无关系CPU 也会因为缓存行失效而频繁同步导致性能大幅下降。我之前在写一个统计组件时定义了一个数组long[] counters new long[8]八个线程各自独立更新counters[i]理论上应该互不干扰结果性能怎么压都上不去。后来用缓存行填充的方式把每个变量隔开到不同缓存行性能才有明显改善。Java 里可以用Contended注解做缓存行填充不过要在启动参数里加上-XX:-RestrictContended才生效。这种问题在数据量小但访问频率极高的场景比如计数器、多线程统计数据帧里最容易冒头。4.4 常见并发故障速查表问题现象可能原因排查工具/命令处理思路接口随机超时CPU 不高线程池队列积压线程池监控、jstack检查队列大小、下游耗时、核心线程数死锁进程假死加锁顺序不一致jstack 看 deadlock 段统一加锁顺序、tryLock 超时数据偶发不一致组合操作非原子代码审查、压测复现改用复合原子方法或加锁线程数持续上涨任务异常未退出jstack 统计线程状态定位长期 RUNNABLE 线程检查循环退出条件内存逐渐涨满ThreadLocal 未清理heap dump、MAT使用后 remove()避免存储大对象并发度上不去伪共享压测对比、perf缓存行填充、重新设计数据结构5. 给新手的进阶路线与常见弯路5.1 从“会用 API”到“能调性能”的方法我推荐的学习路径分成五个阶段前两个阶段是建立基础后三个阶段是冲向实战。第一个阶段把线程和 JMM 啃透。线程怎么创建、状态怎么转换、synchronized和volatile的本质区别这些是万层高楼的钢筋水泥。第二个阶段用熟 JUC 工具类。ReentrantLock、CountDownLatch、CyclicBarrier、Semaphore、ConcurrentHashMap每个都写一个 demo模仿真实业务去用比如用Semaphore实现一个简单的连接池限流。第三个阶段聚焦线程池和异步编排。把我上面说的线程池参数计算方式实践一遍尝试用CompletableFuture改写一个同步慢接口对比耗时数据。第四个阶段深入底层原理。试着读ConcurrentHashMap的 put 源码、AQS 的 acquire 流程、ThreadPoolExecutor的 execute 流程不需要逐行读懂但关键方法的流程要有能力画出来。第五个阶段结合性能分析工具做调优。jstack、jstat、arthas、VisualVM这些工具至少熟练掌握两三个遇到线上问题时能用工具定位而不是靠猜。到这个阶段并发编程就算真正入了门。5.2 学习时最容易走的弯路一个很常见的弯路是“只背八股不写代码”。网上关于并发编程的面试题非常多很多人能流利背诵 volatile 的可见性原理、synchronized 的锁升级过程但让他写一个用多线程并发拉取接口并汇总结果的 demo就不知道从哪下手。八股是结果不是起点写代码才是理解原理的唯一途径。另一个弯路是“过早深钻源码”。我以前就犯过这个错误刚学完 JUC 容器就去啃 AQS 的源码结果在 acquireQueued 的循环里转不出来越看越挫败。正确做法是先用、再读、再优化等自己踩过坑之后看源码时才会产生“原来是这样解决我的问题”的共鸣感。如果看书我会推荐两本做互补阅读一本偏全面系统适合建立知识地图另一本偏并发实战适合在有一定基础后深度学习锁、并发容器、执行框架这些核心机制的底层设计。记住一点这类经典书没有 PDF 捷径认认真真读纸质版或者正版电子书边读边写代码做笔记效果远好于收藏一堆资源链接。最后分享一点我的个人体会这几年带过一些新人也帮朋友排查过不少线上并发问题我最大的感受是并发编程这门手艺不是靠看内容看会的而是靠一遍遍写 demo、一次次踩坑试错的“肌肉记忆”。那套阿里并发编程全优笔记最打动我的地方是它把最容易让人望而生畏的底层机制拆解得足够清晰让我按图索骥地把知识点一个一个落到代码里验证。如果你也打算好好攻克并发这一关我建议你给自己定一个目标把线程池参数计算、CompletableFuture 编排、ConcurrentHashMap 原子方法这三个高频场景写成完整可运行的代示例放在自己的代码库里。遇到新情况就回来翻笔记、翻源码、跑测试去验证。等你能用自己的话把“为什么这个方案在这个场景下会出问题、换另一个方案为什么就好了”讲清楚并发编程这块硬骨头就算真正啃下来了。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。