1. 程式人生 > >如何學習Java多執行緒

如何學習Java多執行緒

最近一段時間,我對《Java併發程式設計實踐》這本經典而又有些難懂的書籍,嘗試用了一些簡單有趣、通俗易懂的方式進行解讀,現整理成GitBook(文末有連結),方便大家閱讀。

為什麼要解讀這本書

因為這是一本經典卻又難懂的書。

這本書的經典我想不必多講了,幾乎所有想學習Java併發的同學,都會被推薦去看這本書(雖然他們中的大多數在看了不到三分之一之後就放棄了),作為一本書籍,最重要的是系統性和準確性,這本書涵蓋了Java併發中幾乎所有基礎知識點,並且大多數章節都配有實際案例,是一本非常值得收藏的Java併發參考手冊。

那麼為什麼說這本書難懂呢?
總的來說有以下幾點:

  • 理論過多。舉個例子,書中第五章,在講Java併發的一些基礎構建模組時(ConcurrentHashMap、CopyOnWriteArrayList、Future這些),前面用了很多篇幅講這些類的理論知識,到章節最後才用一個實際案例將這些知識串起來,而很多讀者在看前面那些枯燥乏味的理論性講解時,就已經消耗了太多意志力,導致最後根本沒精力看最後的案例;
  • 有點跳躍。書中對一些知識點的講解,並沒有完全講透,有些只是一筆帶過,讀者看到難免就會心裡好多個疑問,然後就試圖通過上下文去理解作者的意思,最後又消耗了大量意志力,導致最終的棄讀;
  • 中文翻譯彆扭。這是很多經典技術書籍的通病了,本身這本書就很難懂,翻譯的彆扭,就更難懂了。

針對上面這些問題,我採用了以下方式進行解讀:

  • 用講故事的方式進行講解。讓文章兼具知識性和娛樂性,讓讀者閱讀時不會感到枯燥;
  • 先案例後理論。我把書中放在章節最後的案例,挪到了文章的開頭,讓讀者先對知識有了大概的瞭解,同時引發讀者的好奇心,在看文章後面的偏理論解讀的時候,不會昏昏欲睡;
  • 不侷限於書籍本身。和大多數讀者一樣,我在看這本書的時候,也經常會卡殼,然後翻尋上下文,依舊百思不得其解。這時候就需要用到搜尋引擎了,所以你經常會在我的文章末尾看到除了《Java併發程式設計實踐》以外的其他參考文獻;
  • 必要時看原著。上面說了,有些段落的中文翻譯實在看著彆扭,這時候就需要看回原著,看看作者自己是如何表述的。

解讀脈絡

我這次解讀的內容,也許只包含了Java併發中20%的知識,但這20%的知識,已經足以涵蓋平時80%的使用場景。下面簡單梳理一下這份解讀的脈絡。

1、為什麼要使用執行緒池
首先,你學習Java多執行緒,得知道為什麼要使用多執行緒吧?幹嘛不老老實實使用單執行緒呢?這部分比較簡單,書裡講的也很清楚,網上一搜資料也一大把,所以這部分不作解讀 ( ̄▽ ̄)~

2、如何寫出執行緒不安全的程式碼
好,現在你知道為什麼要學Java多執行緒了。
那麼當我們談學習多執行緒時,我們是在談學習什麼呢?談如何建立執行緒嗎?不是,多執行緒裡的大多數知識,都是在講如何在多執行緒的環境下,保證程式碼的執行緒安全性,所以,接下來,你要了解,如何寫出執行緒不安全的程式碼,知道什麼樣的程式碼是執行緒不安全的,你才會去想如何才能讓它執行緒安全。

3、兩個最基礎的關鍵字
現在你寫出了執行緒不安全的程式碼,是時候想想要怎樣把它們變成執行緒安全的了。
在Java中,實現執行緒安全,最最基礎的就是兩個關鍵字,volatilesynchronize
volatile用的比較少,但是通過對它的學習,你可以瞭解Java記憶體模型,學會透過JVM去看執行緒問題,這是一個思考正規化的提升Volatile趣談——我是怎麼把貝克漢姆的進球弄丟的
synchronize,無需多言,不管是我們自己寫的程式碼,還是JDK裡的各個執行緒安全類,如ConcurrentHashMap,HashTable,大多都是利用synchronize來實現的執行緒安全:如何用一句話介紹synchronize的內涵

4、學會委託
學會了volatile和synchronize,以後就可以靠著兩兄弟打遍天下無敵手了?
理論上可行,不過就像那句話說的,拿著錘子的人,看誰都是釘子。要想建一棟大樓,我們不能只有錘子,我們還需要起重機。Java就給了我們很多牛哄哄的起重機,比如ConcurrentHashMap,想想看,每次你想讓你的Map執行緒安全,都要自己手動加上synchronize,這多麻煩,有了ConcurrentHashMap,我們只要把執行緒安全的重任,委託給它去實現就ok了。
Java中可以被委託的類還有很多,大體上分為三類,同步容器、併發容器和同步工具類,我的解讀,也是通過一個簡單的快取案例,展示瞭如何把一個原本執行緒不安全的程式碼,通過synchronize改為執行緒安全,再通過委託,強化為效能更猛的快取器:Java趣談——如何構建一個高效且可伸縮的快取

5、學點內功——執行緒池
現在你已經掌握了極強的外功了,十八般武藝樣樣精通,可以去武林大會挑戰武林盟主了嗎?還不行,光有極強的外功,卻沒有與之匹配的內功,只會讓你走火入魔。
Java多執行緒也是如此,上面講的都是外功,教你如何使用各種工具實現執行緒安全,但是想想看,實際專案中,你真的可以每個任務過來都給它建立一條執行緒嗎?肯定不行嘛,記憶體會撐爆的!所以,你還需要掌握一項管控執行緒數量的技術——執行緒池,我將通過一個Web伺服器的案例,給你展示為什麼要使用執行緒池以及如何將無執行緒數量管控的程式碼改為由執行緒池管控的程式碼:Java趣談——如何像Tomcat一樣處理請求
另外,我還將從Java併發大師Doug Lea的視角,帶你瞭解Java執行緒池背後的原理:Java執行緒池是如何誕生的?

6、學點設計——併發方案
學會了外功,又掌握了內功,可以上江湖闖蕩了嗎?等等,還有一點,你要知道什麼才是你應該出手的時機,你總不能一上來就放大招殺敵一千自損四百吧。Java併發也是如此,你要知道,在什麼情況下,應該對任務進行並行化處理,以及哪種情況下並行處理效果更好,我用了一個頁面渲染器的案例,給你展示了,如何對併發方案進行設計和優化:Java趣談——如何寫出一個高效的頁面渲染器

以上就是我對《Java併發程式設計實踐》中,足以解決你80%的併發問題的20%知識的解讀,其他沒有解讀的包括:

  • 如何取消和關閉執行緒
  • 如何避免執行緒的活躍性風險
  • 如何提升效能和可伸縮性
  • 如何測試併發程式
  • 顯示鎖及其原理
  • 如何自定義同步工具
  • 原子變數及其原理
  • 非阻塞演算法及其原理

難道這些知識不重要嗎?並不是,只是我還沒細看解讀不了罷了 (〃’▽’〃)
那不掌握這些知識,可以出山了嗎?可以,只要你把《Java併發程式設計實踐》這本書放在桌子旁邊,知道有問題要去看哪部分就可以了,比如你寫了一個併發程式,想測試一下,卻不知道從何入手,翻開書,看索引,第12章,併發程式的測試,看,學,學以致用,就ok了。

當然,我的解讀只是為了幫助大家更好的理解書中的將的知識,所以對於我解讀過的章節,大家如果想深入學習,還是要翻開書,研究一番的,只不過在看了我的解讀之後,你理解起來會更輕鬆,學習起來會更有目的性,效率會更高。

其他推薦書籍

不管什麼領域,要想全面的學習一項技術,光看一本書都是不夠的。
如果說學習《Java併發程式設計實踐》這本權威經典之作,是給自己搭建了一個Java多執行緒的知識框架的話,那麼看其他作者寫的同主題的書,就是主動的尋求對已有框架的進一步驗證和衝擊

那麼還有什麼Java多執行緒書值得去看一看呢?
《Java併發程式設計實踐》中,用的是常規的視角來講Java多執行緒的,所謂常規,就是由淺到深,層層遞進。而我們也可以換一個視角,比如用設計模式的視角來學習。用這個視角來講Java多執行緒的開山鼻祖,應該是Doug Lea的Concurrent Programming in Java - Design Principles and Pattern ,不過老人家畢竟水平太高,寫的文章一般人看不懂,所以就有了日本人寫的圖解Java多執行緒設計模式,以及我們中國人寫的Java多執行緒程式設計實戰指南(設計模式篇),大家可以選擇其中一本進行學習,從一個不一樣的視角,看待Java多執行緒。