前言V目录第1章走入并行世界........................................................................................................................................11.1何去何从的并行计算11.1.1忘掉那该死的并行21.1.2可怕的现实:摩尔定律的失效41.1.3柳暗花明:不断地前进51.1.4光明或是黑暗61.2你必须知道的几个概念61.2.1同步(Synchronous)和异步(Asynchronous)71.2.2并发(Concurrency)和并行(Parallelism)81.2.3临界区91.2.4阻塞(Blocking)和非阻塞(Non-Blocking)91.2.5死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock)91.3并发级别111.3.1阻塞(Blocking)111.3.2无饥饿(Starvation-Free)111.3.3无障碍(Obstruction-Free)121.3.4无锁(Lock-Free)121.3.5无等待(Wait-Free)131.4有关并行的两个重要定律131.4.1Amdahl定律131.4.2Gustafson定律161.4.3Amdahl定律和Gustafson定律是否相互矛盾161.5回到Java:JMM171.5.1原子性(Atomicity)181.5.2可见性(Visibility)201.5.3有序性(Ordering)221.5.4哪些指令不能重排:Happen-Before规则271.6参考文献27第2章Java并行程序基础..............................................................................................................................292.1有关线程你必须知道的事292.2初始线程:线程的基本操作322.2.1新建线程322.2.2终止线程342.2.3线程中断382.2.4等待(wait)和通知(notify)412.2.5挂起(suspend)和继续执行(resume)线程442.2.6等待线程结束(join)和谦让(yield)482.3volatile与Java内存模型(JMM)502.4分门别类的管理:线程组522.5驻守后台:守护线程(Daemon)542.6先干重要的事:线程优先级552.7线程安全的概念与synchronized57前言VII2.8程序中的幽灵:隐蔽的错误612.8.1无提示的错误案例612.8.2并发下的ArrayList622.8.3并发下诡异的HashMap632.8.4初学者常见问题:错误的加锁662.9参考文献68第3章JDK并发包..........................................................................................................................................703.1多线程的团队协作:同步控制703.1.1synchronized的功能扩展:重入锁713.1.2重入锁的好搭档:Condition条件803.1.3允许多个线程同时访问:信号量(Semaphore)833.1.4ReadWriteLock读写锁853.1.5倒计时器:CountDownLatch873.1.6循环栅栏:CyclicBarrier893.1.7线程阻塞工具类:LockSupport923.2线程复用:线程池953.2.1什么是线程池963.2.2不要重复发明轮子:JDK对线程池的支持973.2.3刨根究底:核心线程池的内部实现1023.2.4超负载了怎么办:拒绝策略1063.2.5自定义线程创建:ThreadFactory1093.2.6我的应用我做主:扩展线程池1103.2.7合理的选择:优化线程池线程数量1123.2.8堆栈去哪里了:在线程池中寻找堆栈1133.2.9分而治之:Fork/Join框架1173.3不要重复发明轮子:JDK的并发容器1213.3.1超好用的工具类:并发集合简介1213.3.2线程安全的HashMap1223.3.3有关List的线程安全1233.3.4高效读写的队列:深度剖析ConcurrentLinkedQueue1233.3.5高效读取:不变模式下的CopyOnWriteArrayList1293.3.6数据共享通道:BlockingQueue1303.3.7随机数据结构:跳表(SkipList)1343.4参考资料136第4章锁的优化及注意事项.........................................................................................................................1384.1有助于提高“锁”性能的几点建议1394.1.1减小锁持有时间1394.1.2减小锁粒度1404.1.3读写分离锁来替换独占锁1424.1.4锁分离1424.1.5锁粗化1444.2Java虚拟机对锁优化所做的努力1464.2.1锁偏向1464.2.2轻量级锁1464.2.3自旋锁1464.2.4锁消除1464.3人手一支笔:ThreadLocal1474.3.1ThreadLocal的简单使用1484.3.2ThreadLocal的实现原理1494.3.3对性能有何帮助155前言IX4.4无锁1574.4.1与众不同的并发策略:比较交换(CAS)1584.4.2无锁的线程安全整数:AtomicInteger1594.4.3Java中的指针:Unsafe类1614.4.4无锁的对象引用:AtomicReference1624.4.5带有时间戳的对象引用:AtomicStampedReference1654.4.6数组也能无锁:AtomicIntegerArray1684.4.7让普通变量也享受原子操作:AtomicIntegerFieldUpdater1694.4.8挑战无锁算法:无锁的Vector实现1714.4.9让线程之间互相帮助:细看SynchronousQueue的实现1764.5有关死锁的问题1794.6参考文献183第5章并行模式与算法................................................................................................................................1845.1探讨单例模式1845.2不变模式1875.3生产者-消费者模式1905.4高性能的生产者-消费者:无锁的实现1945.4.1无锁的缓存框架:Disruptor1955.4.2用Disruptor实现生产者-消费者案例1965.4.3提高消费者的响应时间:选择合适的策略1995.4.4CPUCache的优化:解决伪共享问题2005.5Future模式2045.5.1Future模式的主要角色2065.5.2Future模式的简单实现2075.5.3JDK中的Future模式2105.6并行流水线2125.7并行搜索2165.8并行排序2185.8.1分离数据相关性:奇偶交换排序2185.8.2改进的插入排序:希尔排序2215.9并行算法:矩阵乘法2265.10准备好了再通知我:网络NIO2305.10.1基于Socket的服务端的多线程模式2305.10.2使用NIO进行网络编程2355.10.3使用NIO来实现客户端2435.11读完了再通知我:AIO2455.11.1AIOEchoServer的实现2455.11.2AIOEcho客户端实现2485.12参考文献249第6章Java8与并发.....................................................................................................................................2516.1Java8的函数式编程简介2516.1.1函数作为一等公民2526.1.2无副作用2526.1.3申明式的(Declarative)2536.1.4不变的对象2546.1.5易于并行2546.1.6更少的代码2546.2函数式编程基础2556.2.1FunctionalInterface注释2556.2.2接口默认方法256前言XI6.2.3lambda表达式2596.2.4方法引用2606.3一步一步走入函数式编程2636.4并行流与并行排序2676.4.1使用并行流过滤数据2676.4.2从集合得到并行流2686.4.3并行排序2686.5增强的Future:CompletableFuture2696.5.1完成了就通知我2696.5.2异步执行任务2706.5.3流式调用2726.5.4CompletableFuture中的异常处理2726.5.5组合多个CompletableFuture2736.6读写锁的改进:StampedLock2746.6.1StampedLock使用示例2756.6.2StampedLock的小陷阱2766.6.3有关StampedLock的实现思想2786.7原子类的增强2816.7.1更快的原子类:LongAdder2816.7.2LongAdder的功能增强版:LongAccumulator2876.8参考文献288第7章使用Akka构建高并发程序..............................................................................................................2897.1新并发模型:Actor2907.2Akka之HelloWorld2907.3有关消息投递的一些说明2937.4Actor的生命周期2957.5监督策略2987.6选择Actor3037.7消息收件箱(Inbox)3037.8消息路由3057.9Actor的内置状态转换3087.10询问模式:Actor中的Future3117.11多个Actor同时修改数据:Agent3137.12像数据库一样操作内存数据:软件事务内存3167.13一个有趣的例子:并发粒子群的实现3197.13.1什么是粒子群算法3207.13.2粒子群算法的计算过程3207.13.3粒子群算法能做什么3227.13.4使用Akka实现粒子群3237.14参考文献330第8章并行程序调试....................................................................................................................................3318.1准备实验样本3318.2正式起航3328.3挂起整个虚拟机3348.4调试进入ArrayList内部336前言XIII前言关于Java与并行由于单核CPU的主频逐步逼近极限,多核CPU架构成为了一种必然的技术趋势。所以,多线程并行程序便显得越来越重要。并行计算的一个重要应用场景就是服务端编程。可以看到,目前服务端CPU的核心数已经轻松超越10核心,而Java显然已经成为当下最流行的服务端编程语言,因此熟悉和了解基于Java的并行程序开发有着重要的实用价值。本书的体系结构本书立足于实际开发,又不缺乏理论介绍,力求通俗易懂、循序渐进。本