并發(fā)編程領(lǐng)域的扛鼎之作,作者是阿里和1號店的資深Java技術(shù)專家,對并發(fā)編程有非常深入的研究,《Java并發(fā)編程的藝術(shù)》是他們多年一線開發(fā)經(jīng)驗的結(jié)晶。本書的部分內(nèi)容在出版早期發(fā)表在Java并發(fā)編程網(wǎng)和InfoQ等技術(shù)社區(qū),得到了非常高的評價。它選取了Java并發(fā)編程中最核心的技術(shù)進(jìn)行講解,從JDK源碼、JVM、CPU等多角度全面剖析和講解了Java并發(fā)編程的框架、工具、原理和方法,對Java并發(fā)編程進(jìn)行了最為深入和透徹的闡述。
《Java并發(fā)編程的藝術(shù)》內(nèi)容涵蓋Java并發(fā)編程機(jī)制的底層實現(xiàn)原理、Java內(nèi)存模型、Java并發(fā)編程基礎(chǔ)、Java中的鎖、并發(fā)容器和框架、原子類、并發(fā)工具類、線程池、Executor框架等主題,每個主題都做了深入的講解,同時通過實例介紹了如何應(yīng)用這些技術(shù)。
阿里系和1號店資深技術(shù)專家撰寫,Java并發(fā)編程領(lǐng)域的扛鼎之作,內(nèi)容在InfoQ等社群得到高度認(rèn)可
從JDK源碼、JVM、CPU等多角度全面剖析和講解Java并發(fā)編程的框架、原理和核心技術(shù)
隨著大數(shù)據(jù)時代的來臨,程序員可能每天要處理幾十個TB的數(shù)據(jù),如何讓程序快速且安全地處理各種大數(shù)據(jù),就需要掌握不同的并發(fā)編程模型和并發(fā)編程技巧。用戶的一個點擊,需要在毫秒級處理完多個任務(wù),同樣需要并發(fā)編程的參與。
并發(fā)編程是Java語言的重要特性之一,在Java平臺上提供了許多基本的并發(fā)功能來輔助開發(fā)多線程應(yīng)用程序。然而,這些相對底層的并發(fā)功能與上層應(yīng)用程序的并發(fā)語義之間并不存在一種簡單而直觀的映射關(guān)系。因此,如何在Java并發(fā)應(yīng)用程序中正確且高效地使用這些功能就成了Java開發(fā)人員的關(guān)注重點。
《Java并發(fā)編程的藝術(shù)》正是為了解決這個問題而寫的。書中采用循序漸進(jìn)的講解方式,從并發(fā)編程的底層實現(xiàn)機(jī)制入手,逐步介紹了在設(shè)計Java并發(fā)程序時各種重要的技術(shù)、設(shè)計模式與應(yīng)用,同時輔以豐富的示例代碼,使得開發(fā)人員能夠更快地領(lǐng)悟Java并發(fā)編程的要領(lǐng),圍繞著Java平臺的基礎(chǔ)并發(fā)功能快速地構(gòu)建大規(guī)模的并發(fā)應(yīng)用程序。
為什么要寫這本書記得第一次寫并發(fā)編程的文章時還是在2012年,當(dāng)時花了幾個星期的時間寫了一篇文章《深入分析volatile的實現(xiàn)原理》,準(zhǔn)備在自己的博客中發(fā)表。在同事建法的建議下,懷著試一試的心態(tài)投向了InfoQ,慶幸的是半小時后得到InfoQ主編采納的回復(fù),高興之情無以言表。這也是我第一次在專業(yè)媒體上發(fā)表文章,而后在InfoQ編輯張龍的不斷鼓勵和支持下,我陸續(xù)在InfoQ發(fā)表了幾篇與并發(fā)編程相關(guān)的文章,于是便形成了“聊聊并發(fā)”專欄。在這個專欄的寫作過程中,我得到快速的成長和非常多的幫助,在此非常感謝InfoQ的編輯們。2013年,華章的福川兄找到我,問有沒有興趣寫一本書,當(dāng)時覺得自己資歷尚淺,婉言拒絕了。后來和福川兄一直保持聯(lián)系,最后允許我花兩年的時間來完成本書,所以答應(yīng)了下來。由于并發(fā)編程領(lǐng)域的技術(shù)點非常多且深,所以陸續(xù)又邀請了同事魏鵬和朋友曉明一起參與到本書的編寫當(dāng)中。
寫本書的過程也是對自己研究和掌握的技術(shù)點進(jìn)行整理的過程,希望本書能幫助讀者快速掌握并發(fā)編程技術(shù)。
本書一共11章,由三名作者共同編寫完成,其中第3章和第10章節(jié)由程曉明編寫,第4章和第5章由魏鵬編寫,其他7章由方騰飛編寫。
本書特色本書結(jié)合JDK的源碼介紹了Java并發(fā)框架、線程池的實現(xiàn)原理,幫助讀者做到知其所以然。
本書對原理的剖析不僅僅局限于Java層面,而是深入到JVM,甚至CPU層面來進(jìn)行講解,幫助讀者從更底層看并發(fā)技術(shù)。
本書結(jié)合線上應(yīng)用,給出了一些并發(fā)編程實戰(zhàn)技巧,以及線上處理并發(fā)問題的步驟和思路。
方騰飛(花名清英,英文名kiral),
螞蟻金服集團(tuán)技術(shù)專家,從事Java開發(fā)近10年。5年以上的團(tuán)隊管理、項目管理和敏捷開發(fā)經(jīng)驗,崇尚團(tuán)隊合作。曾參與CMS、電子海圖、SOC、ITIL、電子商務(wù)網(wǎng)站和信貸管理系統(tǒng)等項目。目前在螞蟻金服網(wǎng)商銀行貸款管理團(tuán)隊負(fù)責(zé)數(shù)據(jù)采集平臺開發(fā)工作。與同事合作開發(fā)了tala code Review插件,深受阿里數(shù)千名工程師擁躉,并開發(fā)過開源工具jdbcutil(https://github.com/kiral/utils)。創(chuàng)辦了并發(fā)編程網(wǎng),組織翻譯了百余篇國外優(yōu)秀技術(shù)文章,并曾為InfoQ撰寫“聊聊并發(fā)”專欄,在《程序員》雜志撰寫敏捷實踐系列文章
魏 鵬,
阿里巴巴集團(tuán)技術(shù)專家,在阿里巴巴中國網(wǎng)站技術(shù)部工作多年,曾擔(dān)任中國網(wǎng)站交易平臺架構(gòu)師,主導(dǎo)了交易系統(tǒng)服務(wù)化工作,設(shè)計實現(xiàn)的數(shù)據(jù)遷移系統(tǒng)高效地完成了阿里巴巴中國網(wǎng)站交易數(shù)據(jù)到阿里巴巴集團(tuán)的遷移工作。目前在阿里巴巴共享業(yè)務(wù)事業(yè)部從事Java應(yīng)用容器Pandora和服務(wù)框架HSF的相關(guān)工作,其中Java應(yīng)用容器Pandora是阿里巴巴中間件運行的基礎(chǔ),而服務(wù)框架HSF則是阿里巴巴集團(tuán)實現(xiàn)服務(wù)化的主要解決方案,二者在阿里巴巴擁有最為廣泛的使用量。個人平時喜歡閱讀技術(shù)書籍,翻譯一些國外優(yōu)秀文檔,喜歡總結(jié)、樂于分享,對Java應(yīng)用容器、多線程編程以及分布式系統(tǒng)感興趣。
程曉明,
1號店資深架構(gòu)師,從事1號店交易平臺系統(tǒng)的開發(fā),技術(shù)上關(guān)注并發(fā)與NIO。因5年前遇到的一個線上故障,解決過程中對Java并發(fā)編程產(chǎn)生了濃厚的興趣,從此開始了漫長的探索之旅:從底層實現(xiàn)機(jī)制、內(nèi)存模型到Java同步?v觀我自己對Java并發(fā)的學(xué)習(xí)過程,是一個從高層到底層再到高層的一個反復(fù)迭代的過程,我估計很多讀者的學(xué)習(xí)過程應(yīng)該與我類似。文章多見諸《IBM developerWorks》、InfoQ和《程序員》雜志。
前 言
第1章 并發(fā)編程的挑戰(zhàn) 1
1.1 上下文切換 1
1.1.1 多線程一定快嗎 1
1.1.2 測試上下文切換次數(shù)和時長 3
1.1.3 如何減少上下文切換 3
1.1.4 減少上下文切換實戰(zhàn) 4
1.2 死鎖 5
1.3 資源限制的挑戰(zhàn) 6
1.4 本章小結(jié) 7
第2章 Java并發(fā)機(jī)制的底層實現(xiàn)原理 8
2.1 volatile的應(yīng)用 8
2.2 synchronized的實現(xiàn)原理與應(yīng)用 11
2.2.1 Java對象頭 12
2.2.2 鎖的升級與對比 13
2.3 原子操作的實現(xiàn)原理 16
2.4 本章小結(jié) 20
第3章 Java內(nèi)存模型 21
3.1 Java內(nèi)存模型的基礎(chǔ) 21
3.1.1 并發(fā)編程模型的兩個關(guān)鍵問題 21
3.1.2 Java內(nèi)存模型的抽象結(jié)構(gòu) 22
3.1.3 從源代碼到指令序列的重排序 23
3.1.4 并發(fā)編程模型的分類 24
3.1.5 happens-before簡介 26
3.2 重排序 27
3.2.1 數(shù)據(jù)依賴性 28
3.2.2 as-if-serial語義 28
3.2.3 程序順序規(guī)則 29
3.2.4 重排序?qū)Χ嗑程的影響 29
3.3 順序一致性 31
3.3.1 數(shù)據(jù)競爭與順序一致性 31
3.3.2 順序一致性內(nèi)存模型 32
3.3.3 同步程序的順序一致性效果 34
3.3.4 未同步程序的執(zhí)行特性 35
3.4 volatile的內(nèi)存語義 38
3.4.1 volatile的特性 38
3.4.2 volatile寫-讀建立的happens-before關(guān)系 39
3.4.3 volatile寫-讀的內(nèi)存語義 40
3.4.4 volatile內(nèi)存語義的實現(xiàn) 42
3.4.5 JSR-133為什么要增強(qiáng)volatile的內(nèi)存語義 46
3.5 鎖的內(nèi)存語義 47
3.5.1 鎖的釋放-獲取建立的
happens-before關(guān)系 47
3.5.2 鎖的釋放和獲取的內(nèi)存語義 48
3.5.3 鎖內(nèi)存語義的實現(xiàn) 50
3.5.4 concurrent包的實現(xiàn) 54
3.6 final域的內(nèi)存語義 55
3.6.1 final域的重排序規(guī)則 55
3.6.2 寫final域的重排序規(guī)則 56
3.6.3 讀final域的重排序規(guī)則 57
3.6.4 final域為引用類型 58
3.6.5 為什么final引用不能從構(gòu)造函數(shù)內(nèi)“溢出” 59
3.6.6 final語義在處理器中的實現(xiàn) 61
3.6.7 JSR-133為什么要增強(qiáng)f?inal的語義 62
3.7 happens-before 62
3.7.1 JMM的設(shè)計 62
3.7.2 happens-before的定義 64
3.7.3 happens-before規(guī)則 65
3.8 雙重檢查鎖定與延遲初始化 67
3.8.1 雙重檢查鎖定的由來 67
3.8.2 問題的根源 69
3.8.3 基于volatile的解決方案 71
3.8.4 基于類初始化的解決方案 72
3.9 Java內(nèi)存模型綜述 78
3.9.1 處理器的內(nèi)存模型 78
3.9.2 各種內(nèi)存模型之間的關(guān)系 80
3.9.3 JMM的內(nèi)存可見性保證 80
3.9.4 JSR-133對舊內(nèi)存模型的修補 81
3.10 本章小結(jié) 82
第4章 Java并發(fā)編程基礎(chǔ) 83
4.1 線程簡介 83
4.1.1 什么是線程 83
4.1.2 為什么要使用多線程 84
4.1.3 線程優(yōu)先級 85
4.1.4 線程的狀態(tài) 87
4.1.5 Daemon線程 90
4.2 啟動和終止線程 91
4.2.1 構(gòu)造線程 91
4.2.2 啟動線程 92
4.2.3 理解中斷 92
4.2.4 過期的suspend()、resume()和stop() 93
4.2.5 安全地終止線程 95
4.3 線程間通信 96
4.3.1 volatile和synchronized關(guān)鍵字 96
4.3.2 等待/通知機(jī)制 98
4.3.3 等待/通知的經(jīng)典范式 101
4.3.4 管道輸入/輸出流 102
4.3.5 Thread.join()的使用 103
4.3.6 ThreadLocal的使用 105
4.4 線程應(yīng)用實例 106
4.4.1 等待超時模式 106
4.4.2 一個簡單的數(shù)據(jù)庫連接池示例 106
4.4.3 線程池技術(shù)及其示例 110
4.4.4 一個基于線程池技術(shù)的簡單Web服務(wù)器 114
4.5 本章小結(jié) 118
第5章 Java中的鎖 119
5.1 Lock接口 119
5.2 隊列同步器 121
5.2.1 隊列同步器的接口與示例 121
5.2.2 隊列同步器的實現(xiàn)分析 124
5.3 重入鎖 136
5.4 讀寫鎖 140
5.4.1 讀寫鎖的接口與示例 141
5.4.2 讀寫鎖的實現(xiàn)分析 142
5.5 LockSupport工具 146
5.6 Condition接口 147
5.6.1 Condition接口與示例 148
5.6.2 Condition的實現(xiàn)分析 150
5.7 本章小結(jié) 154
第6章 Java并發(fā)容器和框架 155
6.1 ConcurrentHashMap的實現(xiàn)原理與使用 155
6.1.1 為什么要使用ConcurrentHashMap 155
6.1.2 ConcurrentHashMap的結(jié)構(gòu) 156
6.1.3 ConcurrentHashMap的初始化 157
6.1.4 定位Segment 159
6.1.5 ConcurrentHashMap的操作 160
6.2 ConcurrentLinkedQueue 161
6.2.1 ConcurrentLinkedQueue的結(jié)構(gòu) 162
6.2.2 入隊列 162
6.2.3 出隊列 165
6.3 Java中的阻塞隊列 167
6.3.1 什么是阻塞隊列 167
6.3.2 Java里的阻塞隊列 168
6.3.3 阻塞隊列的實現(xiàn)原理 172
6.4 Fork/Join框架 175
6.4.1 什么是Fork/Join框架 175
6.4.2 工作竊取算法 176
6.4.3 Fork/Join框架的設(shè)計 177
6.4.4 使用Fork/Join框架 177
6.4.5 Fork/Join框架的異常處理 179
6.4.6 Fork/Join框架的實現(xiàn)原理 179
6.5 本章小結(jié) 181
第7章 Java中的13個原子操作類 182
7.1 原子更新基本類型類 182
7.2 原子更新數(shù)組 184
7.3 原子更新引用類型 185
7.4 原子更新字段類 187
7.5 本章小結(jié) 188
第8章 Java中的并發(fā)工具類 189
8.1 等待多線程完成的CountDownLatch 189
8.2 同步屏障CyclicBarrier 191
8.2.1 CyclicBarrier簡介 191
8.2.2 CyclicBarrier的應(yīng)用場景 193
8.2.3 CyclicBarrier和CountDownLatch的區(qū)別 195
8.3 控制并發(fā)線程數(shù)的Semaphore 196
8.4 線程間交換數(shù)據(jù)的Exchanger 198
8.5 本章小結(jié) 199
第9章 Java中的線程池 200
9.1 線程池的實現(xiàn)原理 200
9.2 線程池的使用 203
9.2.1 線程池的創(chuàng)建 203
9.2.2 向線程池提交任務(wù) 205
9.2.3 關(guān)閉線程池 205
9.2.4 合理地配置線程池 206
9.2.5 線程池的監(jiān)控 206
9.3 本章小結(jié) 207
第10章 Executor框架 208
10.1 Executor框架簡介 208
10.1.1 Executor框架的兩級調(diào)度模型 208
10.1.2 Executor框架的結(jié)構(gòu)與成員 208
10.2 ThreadPoolExecutor詳解 213
10.2.1 FixedThreadPool詳解 213
10.2.2 SingleThreadExecutor詳解 214
10.2.3 CachedThreadPool詳解 215
10.3 ScheduledThreadPoolExecutor詳解 217
10.3.1 ScheduledThreadPoolExecutor的運行機(jī)制 217
10.3.2 ScheduledThreadPoolExecutor的實現(xiàn) 218
10.4 FutureTask詳解 221
10.4.1 FutureTask簡介 222
10.4.2 FutureTask的使用 222
10.4.3 FutureTask的實現(xiàn) 224
10.5 本章小結(jié) 227
第11章 Java并發(fā)編程實踐 228
11.1 生產(chǎn)者和消費者模式 228
11.1.1 生產(chǎn)者消費者模式實戰(zhàn) 229
11.1.2 多生產(chǎn)者和多消費者場景 231
11.1.3 線程池與生產(chǎn)消費者模式 234
11.2 線上問題定位 234
11.3 性能測試 236
11.4 異步任務(wù)池 238
11.5 本章小結(jié) 240