java多線程:看圖輕鬆搞懂multithreading「開發面試必備良藥」

java多線程:看圖輕鬆搞懂multithreading「開發面試必備良藥」

multithreading


上集回顧

前面文章我從4種鎖到多線程應用最佳舉例走過來,大家看著我給的解決方案完成開發任務完全是沒問題吧。什麼是樂觀鎖、悲觀鎖、分佈式redis緩存鎖、多線程,建議大家把前面的也學習下。不過你也可以先學本篇文章,在回去看前面的。

本集目標

  1. 學習線程、 進程 、併發、 並行、 多線程、線程不安全 概念。
  2. 學習線程狀態機。
  3. Future和Callable,Runnable與Callable的異同。

進程/線程

進程:是資源的基本單位

線程:是進程中的執行單元,CPU調度的基本單位

兩者聯繫:一個線程只能屬於一個進程,而一個進程可以有多個線程,但之少有一個線程(主線程)資源分配給進程,同一個進程的所有線程共享該進程的所有資源。

併發和並行

併發:交替做不同事的能力

並行:同時做不同事的能力

圖文說明:併發是兩個隊列交替使用一臺咖啡機,並行是兩個隊列同時使用兩臺咖啡機

java多線程:看圖輕鬆搞懂multithreading「開發面試必備良藥」

併發與並行的區別

線程不安全原因

Java對象創建過程中,JVM在堆上分配內存,用來存放對象的屬性。由於堆內存由線程共享,多線程環境下可能併發修改屬性,所以有線程安全問題。這圖也是JVM內存模型,共享和私有數據區見圖。

java多線程:看圖輕鬆搞懂multithreading「開發面試必備良藥」

線程安全:當多個線程訪問某個類時,這個類始終都能表現出正確的行為,那麼就稱這個類是線程安全的。

線程狀態機

這個直接上圖說明,一個簡單一個複雜的狀態機

java多線程:看圖輕鬆搞懂multithreading「開發面試必備良藥」



java多線程:看圖輕鬆搞懂multithreading「開發面試必備良藥」

線程狀態說明


1.Thread t=new Thread:new了一個線程對象。

2. 可運行(runnable):線程對象創建後,t.start()方法後進入可運行線程池中,等待被線程調度選中,獲取cpu的使用權 。

3. 運行(running):runnable狀態的線程獲得了cpu 時間片,開始執行程序代碼。

4. 阻塞(block):阻塞狀態是指線程因為某種原因放棄了cpu 使用權,也即讓出了cpu 時間片,暫時停止運行。直到線程進入可運行(runnable)狀態,才有機會再次獲得cpu 時間片 轉到運行(running)狀態。

阻塞的情況分三種,圖中紅線標明:

(一). 等待阻塞:運行(running)的線程執行o.wait()方法,JVM會把該線程放入等待鎖定池中。

(二). 同步阻塞:運行(running)的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入對象鎖定池準備。

(三). 其他阻塞:運行(running)的線程執行Thread.sleep(),JVM會把該線程置為阻塞狀態。當sleep()狀態超時完畢時,線程重新轉入可運行(runnable)狀態。

5. 死亡(dead):線程run()、main() 方法執行結束,或者因異常退出了run()方法,則該線程結束生命週期。死亡的線程不可再次復生。

wait()與sleep()區別

看上圖兩者的區別,應該很好理解了,sleep()小姐姐是抱著鎖睡的,睡醒後馬上就可以去幹活,wait()漢子沒有鎖只能等待通知,才可以去幹活。

調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()或notify()All方法後本線程才進入對象鎖定池準備。

調用sleep()方法的過程中,線程不會釋放對象鎖。

Runnable與Callable的異同

Callable真是強大的不要不要的,有他就夠了

java多線程:看圖輕鬆搞懂multithreading「開發面試必備良藥」

callable-runnable

Future和Callable

Future是用來檢查Callable的狀態,並且當線程執行完後獲得Callable的計算結果

死鎖

多個線程因為相互等待而被永久阻塞的情況,解決方案如下

1.按順序獲取鎖

2.設置鎖超時

下集預告

多線程底層是很複雜,概念又抽象又多,還有面試官也喜歡問

如果覺得對你有幫助請關注,有錯誤請指點,下篇繼續分析【多線程那些高級特性】


分享到:


相關文章: