实战Java高并发程序设计(第2版)
作 译 者:葛一鸣
出版时间:2018-10 千 字 数:525
版 次:01-01 页 数:416
开 本:16开
装 帧:
I S B N :9787121350030
换 版:
所属分类:科技 计算机 编程语言
纸质书定价:¥89.0
在单核CPU时代,单任务在一个时间点只能执行单一程序,随着多核CPU的发展,并行程序开发变得尤为重要。本书主要介绍基于Java的并行程序设计基础、思路、方法和实战。,立足于并发程序基础,详细介绍Java进行并行程序设计的基本方法。第二,进一步详细介绍了JDK对并行程序的强大支持,帮助读者快速、稳健地进行并行程序开发。第三,详细讨论了“锁”的优化和提高并行程序性能级别的方法和思路。第四,介绍了并行的基本设计模式,以及Java 8/9/10对并行程序的支持和改进。第五,介绍了高并发框架Akka的使用方法。第六,详细介绍了并行程序的调试方法。第七,分析Jetty代码并给出一些其在高并发优化方面的例子。本书内容丰富,实例典型,实用性强,适合有一定Java基础的技术开发人员阅读。
目 录
第1章 走入并行世界 1
1.1 何去何从的并行计算 1
1.1.1 忘掉那该死的并行 2
1.1.2 可怕的现实:摩尔定律的失效 4
1.1.3 柳暗花明:不断地前进 5
1.1.4 光明或是黑暗 6
1.2 你必须知道的几个概念 7
1.2.1 同步(Synchronous)和异步(Asynchronous) 7
1.2.2 并发(Concurrency)和并行(Parallelism) 8
1.2.3 临界区 9
1.2.4 阻塞(Blocking)和非阻塞(Non-Blocking) 9
1.2.5 死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock) 10
1.3 并发级别 11
1.3.1 阻塞 11
1.3.2 无饥饿(Starvation-Free) 11
1.3.3 无障碍(Obstruction-Free) 12
1.3.4 无锁(Lock-Free) 13
1.3.5 无等待(Wait-Free) 13
1.4 有关并行的两个重要定律 14
1.4.1 Amdahl定律 14
1.4.2 Gustafson定律 16
1.4.3 是否相互矛盾 17
1.5 回到Java:JMM 18
1.5.1 原子性(Atomicity) 18
1.5.2 可见性(Visibility) 20
1.5.3 有序性(Ordering) 22
1.5.4 哪些指令不能重排:Happen-Before规则 27
第2章 Java并行程序基础 29
2.1 有关线程你必须知道的事 29
2.2 初始线程:线程的基本操作 32
2.2.1 新建线程 32
2.2.2 终止线程 34
2.2.3 线程中断 38
2.2.4 等待(wait)和通知(notify) 41
2.2.5 挂起(suspend)和继续执行(resume)线程 45
2.2.6 等待线程结束(join)和谦让(yeild) 49
2.3 volatile与Java内存模型(JMM) 50
2.4 分门别类的管理:线程组 53
2.5 驻守后台:守护线程(Daemon) 54
2.6 先做重要的事:线程优先级 56
2.7 线程安全的概念与关键字synchronized 57
2.8 程序中的幽灵:隐蔽的 61
2.8.1 无提示的案例 62
2.8.2 并发下的ArrayList 63
2.8.3 并发下诡异的HashMap 64
2.8.4 初学者常见的问题:的加锁 67
第3章 JDK并发包 71
3.1 多线程的团队协作:同步控制 71
3.1.1 关键字synchronized的功能扩展:重入锁 72
3.1.2 重入锁的好搭档:Condition 81
3.1.3 允许多个线程同时访问:信号量(Semaphore) 85
3.1.4 ReadWriteLock读写锁 86
3.1.5 倒计数器:CountDownLatch 89
3.1.6 循环栅栏:CyclicBarrier 91
3.1.7 线程阻塞工具类:LockSupport 94
3.1.8 Guava和RateLimiter限流 98
3.2 线程复用:线程池 101
3.2.1 什么是线程池 102
3.2.2 不要重复发明轮子:JDK对线程池的支持 102
3.2.3 刨根究底:核心线程池的内部实现 108
3.2.4 超负载了怎么办:拒绝策略 112
3.2.5 自定义线程创建:ThreadFactory 115
3.2.6 我的应用我做主:扩展线程池 116
3.2.7 合理的选择:优化线程池线程数量 119
3.2.8 堆栈去哪里了:在线程池中寻找堆栈 120
3.2.9 分而治之:Fork/Join框架 124
3.2.10 Guava中对线程池的扩展 128
3.3 不要重复发明轮子:JDK的并发容器 130
3.3.1 超好用的工具类:并发集合简介 130
3.3.2 线程安全的HashMap 131
3.3.3 有关List的线程安全 132
3.3.4 高效读写的队列:深度剖析ConcurrentLinkedQueue类 132
3.3.5 高效读取:不变模式下的CopyOnWriteArrayList类 138
3.3.6 数据共享通道:BlockingQueue 139
3.3.7 随机数据结构:跳表(SkipList) 144
3.4 使用JMH进行性能测试 146
3.4.1 什么是JMH 147
3.4.2 Hello JMH 147
3.4.3 JMH的基本概念和配置 150
3.4.4 理解JMH中的Mode 151
3.4.5 理解JMH中的State 153
3.4.6 有关性能的一些思考 154
3.4.7 CopyOnWriteArrayList类与ConcurrentLinkedQueue类 157
第4章 锁的优化及注意事项 161
4.1 有助于提高锁性能的几点建议 162
4.1.1 减少锁持有时间 162
4.1.2 减小锁粒度 163
4.1.3 用读写分离锁来替换独占锁 165
4.1.4 锁分离 165
4.1.5 锁粗化 168
4.2 Java虚拟机对锁优化所做的努力 169
4.2.1 锁偏向 169
4.2.2 轻量级锁 169
4.2.3 自旋锁 170
4.2.4 锁消除 170
4.3 人手一支笔:ThreadLocal 171
4.3.1 ThreadLocal的简单使用 171
4.3.2 ThreadLocal的实现原理 173
4.3.3 对性能有何帮助 179
4.4 无锁 182
4.4.1 与众不同的并发策略:比较交换 182
4.4.2 无锁的线程安全整数:AtomicInteger 183
4.4.3 Java中的指针:Unsafe类 185
4.4.4 无锁的对象引用:AtomicReference 187
4.4.5 带有时间戳的对象引用:AtomicStampedReference 190
4.4.6 数组也能无锁:AtomicIntegerArray 193
4.4.7 让普通变量也享受原子操作:AtomicIntegerFieldUpdater 194
4.4.8 挑战无锁算法:无锁的Vector实现 196
4.4.9 让线程之间互相帮助:细看SynchronousQueue的实现 201
4.5 有关死锁的问题 205
第5章 并行模式与算法 209
5.1 探讨单例模式 209
5.2 不变模式 213
5.3 生产者-消费者模式 215
5.4 高性能的生产者-消费者模式:无锁的实现 220
5.4.1 无锁的缓存框架:Disruptor 221
5.4.2 用Disruptor框架实现生产者-消费者模式的案例 222
5.4.3 提高消费者的响应时间:选择合适的策略 225
5.4.4 CPU Cache的优化:解决伪共享问题 226
5.5 Future模式 230
5.5.1 Future模式的主要角色 232
5.5.2 Future模式的简单实现 233
5.5.3 JDK中的Future模式 236
5.5.4 Guava对Future模式的支持 238
5.6 并行流水线 240
5.7 并行搜索 244
5.8 并行排序 246
5.8.1 分离数据相关性:奇偶交换排序 246
5.8.2 改进的插入排序:希尔排序 250
5.9 并行算法:矩阵乘法 254
5.10 准备好了再通知我:网络NIO 258
5.10.1 基于Socket的服务端多线程模式 259
5.10.2 使用NIO进行网络编程 264
5.10.3 使用NIO来实现客户端 272
5.11 读完了再通知我:AIO 274
5.11.1 AIO EchoServer的实现 275
5.11.2 AIO Echo客户端的实现 277
第6章 Java 8/9/10与并发 281
6.1 Java 8的函数式编程简介 281
6.1.1 函数作为一等公民 282
6.1.2 无副作用 283
6.1.3 声明式的(Declarative) 283
6.1.4 不变的对象 284
6.1.5 易于并行 284
6.1.6 更少的代码 284
6.2 函数式编程基础 285
6.2.1 FunctionalInterface注释 285
6.2.2 接口默认方法 286
6.2.3 lambda表达式 290
6.2.4 方法引用 291
6.3 一步一步走入函数式编程 293
6.4 并行流与并行排序 298
6.4.1 使用并行流过滤数据 298
6.4.2 从集合得到并行流 299
6.4.3 并行排序 299
6.5 增强的Future:CompletableFuture 300
6.5.1 完成了就通知我 300
6.5.2 异步执行任务 301
6.5.3 流式调用 303
6.5.4 CompletableFuture中的异常处理 303
6.5.5 组合多个CompletableFuture 304
6.5.6 支持timeout的 CompletableFuture 306
6.6 读写锁的改进:StampedLock 306
6.6.1 StampedLock使用示例 307
6.6.2 StampedLock的小陷阱 308
6.6.3 有关StampedLock的实现思想 310
6.7 原子类的增强 313
6.7.1 更快的原子类:LongAdder 314
6.7.2 LongAdder功能的增强版:LongAccumulator 320
6.8 ConcurrentHashMap的增强 321
6.8.1 foreach操作 321
6.8.2 reduce操作 321
6.8.3 条件插入 322
6.8.4 search操作 323
6.8.5 其他新方法 324
6.9 发布和订阅模式 324
6.9.1 简单的发布订阅例子 326
6.9.2 数据处理链 328
第7章 使用Akka构建高并发程序 331
7.1 新并发模型:Actor 332
7.2 Akka之Hello World 332
7.3 有关消息投递的一些说明 336
7.4 Actor的生命周期 337
7.5 监督策略 341
7.6 选择Actor 346
7.7 消息收件箱(Inbox) 346
7.8 消息路由 348
7.9 Actor的内置状态转换 351
7.10 询问模式:Actor中的Future 354
7.11 多个Actor同时修改数据:Agent 356
7.12 像数据库一样操作内存数据:软件事务内存 359
7.13 一个有趣的例子:并发粒子群的实现 363
7.13.1 什么是粒子群算法 364
7.13.2 粒子群算法的计算过程 364
7.13.3 粒子群算法能做什么 366
目录
前 言
第1章 并发编程的挑战 1
1.1 上下文切换 1
1.1.1 多线程一定快吗 1
1.1.2 测试上下文切换次数和时长 3
1.1.3 如何减少上下文切换 3
1.1.4 减少上下文切换实战 4
1.2 死锁 5
1.3 资源限制的挑战 6
1.4 本章小结 7
第2章 Java并发机制的底层实现原理 8
2.1 volatile的应用 8
2.2 synchronized的实现原理与应用 11
2.2.1 Java对象头 12
2.2.2 锁的升级与对比 13
2.3 原子操作的实现原理 16
2.4 本章小结 20
第3章 Java内存模型 21
3.1 Java内存模型的基础 21
3.1.1 并发编程模型的两个关键问题 21
前言
为什么要写这本书
记得**次写并发编程的文章时还是在2012年,当时花了几个星期的时间写了一篇文章《深入分析volatile的实现原理》,准备在自己的博客中发表。在同事建法的建议下,怀着试一试的心态投向了InfoQ,庆幸的是半小时后得到InfoQ主编采纳的回复,高兴之情无以言表。这也是我**次在媒体上发表文章,而后在InfoQ编辑张龙的不断鼓励和支持下,我陆续在InfoQ发表了几篇与并发编程相关的文章,于是便形成了“聊聊并发”专栏。在这个专栏的写作过程中,我得到快速的成长和非常多的帮助,在此非常感谢InfoQ的编辑们。2013年,华章的福川兄找到我,问有没有兴趣写一本书,当时觉得自己资历尚浅,婉言拒绝了。后来和福川兄一直保持联系,*后允许我花两年的时间来完成本书,所以答应了下来。由于并发编程领域的技术点非常多且深,所以陆续又邀请了同事魏鹏和朋友晓明一起参与到本书的编写当中。
写本书的过程也是对自己研究和掌握的技术点进行整理的过程,希望本书能帮助读者快速掌握并发编程技术。
本书一共11章,由三名作者共同编写完成,其中第3章和第10章节由程晓明编写,第4章和第5章由魏鹏编写,其他7章由方腾飞编写。
本书特色
本书结合JDK的源码介绍了Java并发框架、线程池的实现原理,帮助读者做到知其所以然。
本书对原理的剖析不仅仅局限于Java层面,而是深入到JVM,甚至CPU层面来进行讲解,帮助读者从更底层看并发技术。
本书结合线上应用,给出了一些并发编程实战技巧,以及线上处理并发问题的步骤和思路。
读者对象
Java开发工程师
架构师
并发编程爱好者
开设相关课程的大专院校师生
如何阅读本书
阅读本书之前,你必须有一定的Java基础和开发经验,*好还有一定的并发编程基础。如果你是一名并发编程初学者,建议按照顺序阅读本书,并按照书中的例子进行编码和实战。如果你有一定的并发编程经验,可以把本书当做一个手册,直接看需要学习的章节。以下是各章节的基本介绍。
第1章介绍Java并发编程的挑战,向读者说明进入并发编程的世界可能会遇到哪些问题,以及如何解决。
第2章介绍Java并发编程的底层实现原理,介绍在CPU和JVM这个层面是如何帮助Java实现并发编程的。
第3章介绍深入介绍了Java的内存模型。Java线程之间的通信对程序员完全透明,内存可见性问题很容易困扰Java程序员,本章试图揭开Java内存模型的神秘面纱。
第4章从介绍多线程技术带来的好处开始,讲述了如何启动和终止线程以及线程的状态,详细阐述了多线程之间进行通信的基本方式和等待/通知经典范式。
第5章介绍Java并发包中与锁相关的API和组件,以及这些API和组件的使用方式与实现细节。
^_^:a831c8361aac06faa9967947cccc813e