現(xiàn)代軟件規(guī)模大、實時性要求高,所以掌握提升處理和響應速度的多線程技術勢在必行。本書涵蓋多線程編程的核心庫、方法、原理,透徹講解了高并發(fā)的本質與應對方法,幫助讀者解決高并發(fā)環(huán)境下的業(yè)務瓶頸。
●本書具體內(nèi)容如下。
第1章講解Java多線程的基礎知識,包括Thread類的核心API的使用。
第2章講解在多線程中通過synchronized關鍵字對并發(fā)訪問進行控制的方法,為讀者學習同步知識打好堅實的基礎。
第3章介紹線程間通信,以在多線程中進行數(shù)據(jù)傳遞。
第4章介紹并發(fā)訪問時的同步處理實現(xiàn),包括讀寫鎖(Lock對象)等相關技術點。
第5章剖析定時器Timer類的內(nèi)部原理。定時器在Android開發(fā)中會有深入應用,是很重要的技術點。
第6章介紹單例模式下多線程的全面解決方案。
第7章對前面遺漏的知識點進行補充,使多線程的知識體系更加完整,盡量做到不出現(xiàn)技術空白點。
第8章介紹并發(fā)集合框架,可以大大提升開發(fā)多線程應用程序的效率。
第9章介紹線程池的使用,讓線程管理更規(guī)范、高效。這也是Java程序員面試必問的技術點。
1. 暢銷書作者撰寫,全新升級,新增適用微服務與分布式開發(fā)的并發(fā)工具與Java線程池
2. 全面剖析多線程編程的核心庫、方法、原理,案例式教學,透徹了解高并發(fā)本質與應對方法
●為什么寫作本書
不管是學習JavaSE、JavaEE、JavaWeb,還是學習Java大數(shù)據(jù)、Java移動開發(fā)、Java分布式、Java微服務,多線程編程都是必不可少的核心技術點。本書是首本多線程技術書,自第1版和第2版出版以來,獲得了廣大Java程序員與學習者的關注,在技術論壇、博客、公眾號等平臺涌現(xiàn)了大量針對Java多線程技術的討論與分享。有些讀者在時間根據(jù)書中的知識總結了學習筆記,并在博客上進行分享,這種傳播知識的精神令人贊賞和尊重,知識就要分享與傳播。我也很高興能為國內(nèi)IT知識的體系建設盡微薄之力。
然而本書第1版和第2版出版時,基于Java的分布式/微服務技術還沒有強調性能的想法,只是單純地實現(xiàn)RPC遠程調用即可,但隨著分布式/微服務技術的穩(wěn)定與推廣,我們發(fā)現(xiàn),單機的性能其實仍是分布式/微服務需要關注的基本點,因為只有單機運行環(huán)境的性能上去了,分布式/微服務的整體性能才能得到大幅度的提高,而在這中間一定會涉及兩個技術點:數(shù)據(jù)的組織和線程的管理。掌握了這兩個技術點,讀者就可以自己實現(xiàn)消息隊列,實現(xiàn)對數(shù)據(jù)的入隊和出隊的管理,這完全可以由現(xiàn)成的Java并發(fā)包中的并發(fā)集合工具類實現(xiàn),不需要自己編寫代碼,從而大大提升了程序員的開發(fā)效率,避免了程序員自己重復造輪子的現(xiàn)象。
與此同時,我也收到了很多讀者希望擴展或者深入講解某些知識點的反饋建議,所以決定升級本書。
●第3版與第2版的區(qū)別
第3版注重實戰(zhàn)知識點的更新,主要是增加了針對數(shù)據(jù)的組織的第8章(并發(fā)集合工具類),以及針對線程的管理的第9章(Java線程池)。
第8章介紹了并發(fā)集合框架,這是在多線程環(huán)境下使用較多的集合工具類,它一方面可以大大提升開發(fā)者開發(fā)多線程應用程序的效率,另一方面對數(shù)據(jù)的組織也更具有規(guī)劃性,能夠滿足高并發(fā)環(huán)境下的使用需求。
第9章增加了線程池的使用,讓線程管理更規(guī)范、高效。線程池也是Java程序員面試必問的技術點。該章深入方法參數(shù)與源代碼層面,講解了有界池和無界池應用,可大大提升讀者開發(fā)高性能服務器的能力。
第3版還增加了若干實用的技術點。
第1章中豐富了版JDK中的Thread類的API。
第2章中強化了多線程中重要的理論基石柵欄的解釋與代碼實現(xiàn)。
第3章中增加了以下內(nèi)容:①?volatile關鍵字在同步與可視性方面的案例,并著重講解了該關鍵字在使用方面的注意事項及技巧;②?使用并發(fā)包實現(xiàn)線程間通信的解決方案,以及并發(fā)包中同步鎖的實現(xiàn)原理;③?線程異步通信機制的解釋與版JDK實現(xiàn)代碼。
第5章中優(yōu)化了定時器相關的案例,代碼更加簡潔、明晰。
第7章中細化了Java線程狀態(tài)的切換。
本書寫作秉承大道至簡思想,只介紹Java多線程開發(fā)中值得關注的內(nèi)容,希望能拋磚引玉,以個人的一些想法和見解,為讀者拓展出更深入、更全面的思路。
●本書特色
在本書寫作的過程中,我盡量減少啰唆的語言,全部以Demo式案例來講解技術點的實現(xiàn),使讀者看到代碼及運行結果后就可以知道該項目要解決的是什么問題,類似于網(wǎng)絡中博客的風格,讓讀者用短的時間學習知識點,明白知識點如何應用,以及在使用時要避免什么,從而快速學習并解決問題。
●讀者對象
Java程序員
系統(tǒng)架構師
Java多線程開發(fā)者
Java并發(fā)開發(fā)者
大數(shù)據(jù)開發(fā)者
其他對多線程技術感興趣的人員
●如何閱讀本書
本書本著實用、易懂的原則,用9章來介紹Java多線程相關的技術。
第1章講解了Java多線程的基礎,包括Thread類的核心API的使用。
第2章講解了在多線程中對并發(fā)訪問的控制,主要是synchronized關鍵字的使用。因為此關鍵字在使用上非常靈活,所以該章給出很多案例來說明此關鍵字的用法,為讀者學習同步知識點打好堅實的基礎。
第3章講解了線程之間的通信與交互細節(jié)。該章主要介紹wait()、notifyAll()和notify()方法的使用,使線程間能互相通信,合作完成任務,還介紹了ThreadLocal類的使用,學習完該章,讀者就能在Thread多線程中進行數(shù)據(jù)的傳遞了。
第4章講解了鎖的使用。因為synchronized關鍵字使用起來比較麻煩,所以Java 5及以上版本中提供了鎖(Lock對象),更好地實現(xiàn)了并發(fā)訪問時的同步處理,包括讀寫鎖等。
第5章講解了Timer定時器類,其內(nèi)部原理就是使用多線程技術。定時器是執(zhí)行計劃任務時很重要的技術點,在進行Android開發(fā)時也會有深入的使用。
第6章講解的單例模式雖然很簡單,但如果遇到多線程將會變得非常麻煩。如何在多線程中解決這么棘手的問題呢?該章會全面給出解決方案。
第7章對前面章節(jié)遺漏的技術空白點進行補充,使多線程的知識體系更加完整。
第8章講解了并發(fā)集合框架的使用,幾乎涵蓋所有主流的并發(fā)集合工具類,并細化到API級,包含阻塞和非阻塞的使用等。
第9章講解了線程池的使用,包括讀者應該著重掌握的ThreadPool線程池構造方法參數(shù)的特性以及其他常用API的使用,并詳細講解了線程池內(nèi)部源代碼的實現(xiàn)。
高洪巖
某世界500強公司項目經(jīng)理,有10年Java開發(fā)和項目管理經(jīng)驗,精通Java語言,擅長Java EE、分布式、微服務、高性能服務器架構、智能報表、多線程和高并發(fā)相關的技術內(nèi)容,理論與實踐經(jīng)驗頗豐,也積極參與開源項目的開發(fā)與設計,涉及Dubbo、Jedis、Pulsar、ZooKeeper等主流開源項目。
著有《Java多線程編程核心技術》《Java并發(fā)編程:核心方法與框架》《NIO與Socket編程技術指南》《Java EE核心框架實戰(zhàn)(第2版)》等多本圖書。
第1章 Java多線程技能 1
1.1 進程和線程的定義及多線程的優(yōu)點 1
1.2 使用多線程 5
1.2.1 繼承Thread類 6
1.2.2 使用常見的3個命令分析線程的信息 8
1.2.3 線程隨機性的展現(xiàn) 10
1.2.4 執(zhí)行start()的順序不代表執(zhí)行run()的順序 12
1.2.5 實現(xiàn)Runnable接口 14
1.2.6 使用Runnable接口實現(xiàn)多線程的優(yōu)點 15
1.2.7 public Thread(Runnable target)中的target參數(shù) 16
1.2.8 實例變量共享導致的非線程安全問題與相應的解決方案 18
1.2.9 Servlet技術也會引起非線程安全問題 22
1.2.10 留意i--與System.out.println()出現(xiàn)的非線程安全問題 25
1.2.11 方法run()被JVM所調用 27
1.3 方法currentThread() 27
1.4 方法isAlive() 30
1.5 方法sleep(long millis) 33
1.6 方法sleep(long millis, int nanos) 34
1.7 方法StackTraceElement[] getStack-Trace() 35
1.8 方法static void dumpStack() 36
1.9 方法Map getAllStackTraces() 37
1.10 方法getId() 39
1.11 停止線程 40
1.11.1 停止不了的線程 41
1.11.2 判斷線程是不是停止狀態(tài) 42
1.11.3 清除中斷狀態(tài)的使用場景 44
1.11.4 能停止的線程異常法 48
1.11.5 在sleep狀態(tài)下停止 51
1.11.6 使用stop()暴力停止線程 53
1.11.7 方法stop()與java.lang.Thread-Death異常 55
1.11.8 使用stop()釋放鎖導致數(shù)據(jù)結果不一致 57
1.11.9 使用return;語句停止線程的缺點及相應的解決方案 59
1.12 暫停線程 61
1.12.1 方法suspend()與resume()的使用 62
1.12.2 方法suspend()與resume()的缺點獨占 63
1.12.3 方法suspend()與resume()的缺點數(shù)據(jù)不完整 66
1.12.4 使用LockSupport類實現(xiàn)線程暫停與恢復 67
1.13 方法yield() 69
1.14 線程的優(yōu)先級 70
1.14.1 線程優(yōu)先級的繼承特性 71
1.14.2 線程優(yōu)先級的規(guī)律性 72
1.14.3 線程優(yōu)先級的隨機性 75
1.14.4 看誰跑得快 76
1.15 守護線程 78
1.16 并發(fā)與并行 79
1.17 同步與異步 80
1.18 多核CPU不一定比單核CPU運行快 81
1.19 本章小結 82
第2章 對象及變量的并發(fā)訪問 83
2.1 synchronized同步方法 83
2.1.1 方法內(nèi)的變量是線程安全的 83
2.1.2 實例變量非線程安全問題及解決方案 85
2.1.3 同步synchronized在字節(jié)碼指令中的原理 88
2.1.4 多個對象多個鎖 90
2.1.5 synchronized方法將對象作為鎖 92
2.1.6 臟讀與解決 97
2.1.7 synchronized鎖重入 99
2.1.8 繼承環(huán)境下的鎖重入 100
2.1.9 出現(xiàn)異常,鎖自動釋放 102
2.1.10 非同步方法?:不使用synchronized重寫方法 104
2.2 synchronized同步語句塊 106
2.2.1 synchronized方法的弊端 106
2.2.2 synchronized同步代碼塊的使用 109
2.2.3 用同步代碼塊解決同步方法的弊端 111
2.2.4 一半異步,一半同步 112
2.2.5 synchronized代碼塊間的同步性 114
2.2.6 方法println()也是同步的 116
2.2.7 驗證synchronized(this)同步代碼塊是鎖定當前對象的 117
2.2.8 將任意對象作為鎖 119
2.2.9 多個鎖就是異步執(zhí)行 121
2.2.10 驗證方法被調用是隨機的 124
2.2.11 不同步導致的邏輯錯誤與解決方案 125
2.2.12 細化驗證3個結論 129
2.2.13 類對象的單例性 134
2.2.14 靜態(tài)同步?:synchronized方法與synchronized(class)代碼塊 135
2.2.15 同步synchronized方法可以對類的所有對象實例起作用 139
2.2.16 同步synchronized(class)代碼塊可以對類的所有對象實例起作用 141
2.2.17 String常量池特性與同步問題 143
2.2.18 synchronized方法無限等待問題與解決方案 146
2.2.19 多線程的死鎖 148
2.2.20 內(nèi)置類與靜態(tài)內(nèi)置類 150
2.2.21 內(nèi)置類與同步?:實驗1 153
2.2.22 內(nèi)置類與同步?:實驗2 155
2.2.23 鎖對象改變導致異步執(zhí)行 156
2.2.24 鎖對象不改變依然是同步執(zhí)行 159
2.2.25 同步寫法案例比較 161
2.2.26 方法holdsLock(Object obj)的使用 161
2.2.27 臨界區(qū) 162
2.3 volatile關鍵字 162
2.3.1 可見性的測試 163
2.3.2 原子性與非原子性的測試 171
2.3.3 禁止代碼重排序的測試 179
2.4 本章小結 190
第3章 線程間通信 191
3.1 wait/ notify機制 191
3.1.1 不使用wait/notify機制進行通信的缺點 191
3.1.2 什么是wait/notify機制 194
3.1.3 wait/notify機制的原理 194
3.1.4 方法wait()的基本用法 195
3.1.5 使用代碼完整實現(xiàn)wait /notify機制 196
3.1.6 使用wait/notify機制實現(xiàn)線程銷毀 198
3.1.7 對業(yè)務代碼進行封裝 200
3.1.8 線程狀態(tài)的切換 203
3.1.9 方法wait()導致鎖立即釋放 204
3.1.10 方法sleep()不釋放鎖 206
3.1.11 方法notify()不立即釋放鎖 206
3.1.12 方法interrupt()遇到方法wait() 208
3.1.13 方法notify()只通知一個線程 210
3.1.14 方法notifyAll()通知所有線程 212
3.1.15 方法wait(long)的基本用法 213
3.1.16 方法wait(long)自動向下運行的條件 215
3.1.17 通知過早與相應的解決方案 218
3.1.18 等待條件發(fā)生變化 220
3.1.19 生產(chǎn)者/消費者模式實現(xiàn) 224
3.1.20 在管道中傳遞字節(jié)流 239
3.1.21 在管道中傳遞字符流 241
3.1.22 利用wait/notify機制實現(xiàn)交叉?zhèn)浞?244
3.1.23 方法sleep()和wait()的區(qū)別 247
3.2 方法join()的使用 247
3.2.1 學習方法join()前的鋪墊 247
3.2.2 用方法join()解決問題 248
3.2.3 方法join()和interrupt()出現(xiàn)異常 250
3.2.4 方法join(long)的使用 252
3.2.5 方法join(long)與sleep(long)的區(qū)別 254
3.2.6 方法join()后的代碼提前運行 257
3.2.7 方法join(long millis, int nanos)的使用 261
3.3 類ThreadLocal的使用 262
3.3.1 方法get()與null 262
3.3.2 類ThreadLocal存取數(shù)據(jù)流程分析 263
3.3.3 驗證線程變量的隔離性 266
3.3.4 解決get()返回null的問題 270
3.3.5 驗證重寫initialValue()方法的隔離性 271
3.3.6 使用remove()方法的必要性 272
3.4 類InheritableThreadLocal的使用 276
3.4.1 類ThreadLocal不能實現(xiàn)值繼承 277
3.4.2 使用InheritableThreadLocal體現(xiàn)值繼承特性 278
3.4.3 值繼承特性在源代碼中的執(zhí)行流程 280
3.4.4 父線程有的值,子線程還是舊值?:不可變類型 285
3.4.5 子線程有的值,父線程還是舊值?:不可變類型 286
3.4.6 子線程可以感應對象屬性值的變化?:可變類型 288
3.4.7 重寫childValue方法實現(xiàn)對繼承值的加工 291
3.5 本章小結 291
第4章 鎖的使用 292
4.1 使用ReentrantLock類 292
4.1.1 使用ReentrantLock實現(xiàn)同步 292
4.1.2 驗證多代碼塊間的同步性 294
4.1.3 方法await()的錯誤用法與相應的解決方案 297
4.1.4 使用方法await()和方法signal()實現(xiàn)wait/notify 300
4.1.5 方法await()暫停的原理 302
4.1.6 通知部分線程?:錯誤用法 306
4.1.7 通知部分線程?:正確用法 308
4.1.8 實現(xiàn)生產(chǎn)者/消費者模式一對一交替打印 311
4.1.9 實現(xiàn)生產(chǎn)者/消費者模式多對多交替打印 313
4.1.10 公平鎖與非公平鎖 315
4.1.11 方法getHoldCount()的使用 318
4.1.12 方法getQueueLength()的使用 319
4.1.13 方法getWaitQueueLength(Condition condition)的使用 321
4.1.14 方法hasQueuedThread(Thread thread)的使用 322
4.1.15 方法hasQueuedThreads()的使用 323
4.1.16 方法hasWaiters(Condition condition)的使用 324
4.1.17 方法isFair()的使用 326
4.1.18 方法isHeldByCurrentThread()的使用 326
4.1.19 方法isLocked()的使用 327
4.1.20 方法lockInterruptibly()的使用 328
4.1.21 方法tryLock()的使用 330
4.1.22 方法tryLock(long timeout, Time-Unit unit)的使用 331
4.1.23 方法await(long time, TimeUnit unit)的使用 333
4.1.24 方法awaitNanos(long nanos-Timeout)的使用 334
4.1.25 方法awaitUntil(Date deadline)的使用 335
4.1.26 方法awaitUninterruptibly()的使用 337
4.1.27 實現(xiàn)線程按順序執(zhí)行業(yè)務 339
4.2 使用ReentrantReadWriteLock類 342
4.2.1 類ReentrantLock的缺點 342
4.2.2 讀讀共享 344
4.2.3 寫寫互斥 344
4.2.4 讀寫互斥 345
4.2.5 寫讀互斥 346
4.3 本章小結 347
第5章 定時器 348
5.1 定時器的使用 348
5.1.1 方法schedule(TimerTask task, Date time)的測試 349
5.1.2 方法schedule(TimerTask task, Date f?irstTime, long period)的測試 357
5.1.3 方法schedule(TimerTask task, long delay)的測試 365
5.1.4 方法schedule(TimerTask task, long delay, long period)的測試 365
5.1.5 方法scheduleAtFixedRate(TimerTask task, Date f?irst-Time, long period)的測試 366
5.2 本章小結 374
第6章 單例模式與多線程 375
6.1 單例模式與多線程 375
6.1.1 立即加載/餓漢模式 375
6.1.2 延遲加載/懶漢模式 377
6.1.3 使用靜態(tài)內(nèi)置類實現(xiàn)單例模式 388
6.1.4 序列化與反序列化的單例模式實現(xiàn) 389
6.1.5 使用static代碼塊實現(xiàn)單例模式 392
6.1.6 使用enum枚舉數(shù)據(jù)類型實現(xiàn)單例模式 393
6.1.7 完善使用enum枚舉實現(xiàn)單例模式 394
6.2 本章小結 396
第7章 拾遺增補 397
7.1 線程的狀態(tài) 397
7.1.1 驗證NEW、RUNNABLE和TERMINATED 399
7.1.2 驗證TIMED_WAITING 400
7.1.3 驗證BLOCKED 401
7.1.4 驗證WAITING 403
7.2 線程組 404
7.2.1 線程對象關聯(lián)線程組?:一級關聯(lián) 404
7.2.2 線程對象關聯(lián)線程組?:多級關聯(lián) 406
7.2.3 線程組自動歸屬特性 407
7.2.4 獲取根線程組 408
7.2.5 線程組內(nèi)加線程組 409
7.2.6 組內(nèi)的線程批量停止 409
7.2.7 遞歸取得與非遞歸取得組內(nèi)對象 410
7.3 Thread.activeCount()方法的使用 412
7.4 Thread.enumerate(Thread tarray[])方法的使用 412
7.5 再次驗證線程執(zhí)行有序性 412
7.6 類SimpleDateFormat非線程安全 414
7.6.1 出現(xiàn)異常 415
7.6.2 解決方法1 417
7.6.3 解決方法2 418
7.7 線程中出現(xiàn)異常的處理 420
7.7.1 線程出現(xiàn)異常的默認行為 420
7.7.2 使用setUncaughtException-Handler()方法進行異常處理 421
7.7.3 使用setDefaultUncaught-ExceptionHandler()方法進行異常處理 422
7.8 線程組內(nèi)處理異常 423
7.9 線程異常處理的優(yōu)先性 426
7.10 本章小結 431
第8章 并發(fā)集合框架 432
8.1 集合框架結構 432
8.1.1 接口Iterable 432
8.1.2 接口Collection 432
8.1.3 接口List 433
8.1.4 接口Set 434
8.1.5 接口Queue 435
8.1.6 接口Deque 435
8.2 非阻塞隊列 435
8.2.1 類ConcurrentHashMap的使用 436
8.2.2 類ConcurrentSkipListMap的使用 442
8.2.3 類ConcurrentSkipListSet的使用 444
8.2.4 類ConcurrentLinkedQueue的使用 447
8.2.5 類ConcurrentLinkedDeque的使用 451
8.2.6 類CopyOnWriteArrayList的使用 453
8.2.7 類CopyOnWriteArraySet的使用 454
8.3 阻塞隊列 456
8.3.1 類ArrayBlockingQueue與公平/非公平鎖的使用 456
8.3.2 類PriorityBlockingQueue的使用 461
8.3.3 類LinkedBlockingQueue的使用 463
8.3.4 類LinkedBlockingDeque的使用 463
8.3.5 類SynchronousQueue的使用 463
8.3.6 類DelayQueue的使用 466
8.3.7 類LinkedTransferQueue的使用 467
8.4 本章小結 476
第9章 線程池類ThreadPoolExecutor的使用 477
9.1 Executor接口介紹 477
9.2 使用Executors工廠類創(chuàng)建線程池 481
9.2.1 使用newCachedThreadPool()方法創(chuàng)建無界線程池 481
9.2.2 驗證newCachedThreadPool()方法創(chuàng)建線程池和線程復用特性 483
9.2.3 使用newCachedThreadPool (ThreadFactory)方法定制線程工廠 486
9.2.4 使用newCachedThread-Pool()方法創(chuàng)建無界線程池的缺點 487
9.2.5 使用newFixedThreadPool(int)
方法創(chuàng)建有界線程池 488
9.2.6 使用newSingleThread-Executor()方法創(chuàng)建單一線程池 490
9.3 ThreadPoolExecutor類的使用 491
9.3.1 隊列LinkedBlocking-Queue、ArrayBlocking-Queue和Synchronous-Queue的基本使用 491
9.3.2 構造方法參數(shù)詳解 495
9.3.3 方法shutdown()和shutdownNow() 521
9.3.4 方法List shutdown-Now()返回值的作用 525
9.3.5 方法shutdown()和shutdown-Now()與中斷 527
9.3.6 方法isShutdown() 529
9.3.7 方法isTerminating()和isTerminated() 530
9.3.8 方法awaitTermination(long timeout,TimeUnit unit) 531
9.3.9 工廠ThreadFactory Thread UncaughtExceptionHandler處理異常 533
9.3.10 方法set/getRejected-ExecutionHandler() 537
9.3.11 方法allowsCoreThreadTime-Out和allowCoreThreadTime-Out(bool) 539
9.3.12 方法prestartCoreThread()和prestartAllCoreThreads() 541
9.3.13 方法getCompletedTask-Count() 542
9.3.14 線程池ThreadPoolExecutor的拒絕策略 543
9.3.15 方法afterExecute()和beforeExecute() 549
9.3.16 方法remove(Runnable)的使用 551
9.3.17 多個get方法的測試 555
9.4 本章小結 558