java多線程基礎必備

目錄

線程概述

線程的創建和啓動

線程的生命週期

控制線程

設置優先級

yield

sleep

join   

線程同步

線程安全問題

synchronized

block

線程通信

傳統

condition

阻塞隊列

線程池

threadLocal

參考文章


 

線程概述

這部分需要理解2個點:
a、線程(Thread) vs 進程(Process)
b、多線程的優勢

 

線程的創建和啓動

a、繼承Thread類
b、實現Runnable接口
小結:鑑於java單繼承的考慮,一般使用實現Runnable來創建進程。

 

線程的生命週期

Java線程具有五中基本狀態

新建狀態(New):當線程對象對創建後,即進入了新建狀態,如:Thread t = new MyThread();

就緒狀態(Runnable):當調用線程對象的start()方法,線程即進入就緒狀態。處於就緒狀態的線程,只是說明此線程已經做好了準備,隨時等待CPU調度執行,並不是說執行了t.start()立即就會執行;

運行狀態(Running):當CPU開始調度處於就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。
注:就緒狀態是進入到運行狀態的唯一入口。

阻塞狀態(Blocked):處於運行狀態中的線程由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,纔有機會再次被CPU調用以進入到運行狀態。根據阻塞產生的原因不同,阻塞狀態又可以分爲三種:

1.等待阻塞:運行狀態中的線程執行wait()方法,使本線程進入到等待阻塞狀態;
2.同步阻塞 -- 線程在獲取synchronized同步鎖失敗(因爲鎖被其它線程所佔用),它會進入同步阻塞狀態;
3.其他阻塞 -- 通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。

死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

 

舉個通俗一點的例子來解釋上面五種狀態,比如上廁所:

你平時去商城上廁所,準備去上廁所就是新建狀態(new),上廁所要排隊,排隊就是就緒狀態(Runnable),有坑位了,輪到你了,拉屎就是運行狀態(Running),你拉完屎發現沒有手紙,要等待別人給你送紙過來,這個狀態就是阻塞(Blocked),等你上完廁所出來,上廁所這件事情結束了就是死亡(Dead)狀態了。

注意:便祕也是阻塞狀態,你便祕太久了,別人等不及了,把你趕走,這個就是掛起;還有一種情況,你便祕了,別人等不及了,跟你說你先出去醞釀一下,5分鐘後再過來拉屎,這就是睡眠。

 

控制線程

設置優先級

從就緒(runnable)進行選取,優先級高的線程被選中執行的概率就大(但不是絕對的)。每個線程在執行時都具有一定的優先級,優先級高的線程具有較多的執行機會。每個線程默認的優先級都與創建它的線程的優先級相同。main線程默認具有普通優先級。

設置線程優先級:setPriority(int priorityLevel)。參數priorityLevel範圍在1-10之間,常用的有如下三個靜態常量值:

MAX_PRIORITY:10

MIN_PRIORITY:1

NORM_PRIORITY:5

獲取線程優先級:getPriority()。


yield

線程讓步:當調用線程的yield()方法時,線程從運行狀態轉換爲就緒狀態。

 

sleep

線程睡眠:讓當前的正在執行的線程暫停指定的時間,並進入阻塞狀態。在其睡眠的時間段內,該線程由於不是處於就緒狀態,因此不會得到執行的機會。即使此時系統中沒有任何其他可執行的線程,出於sleep()中的線程也不會執行。因此sleep()方法常用來暫停線程執行。

 

join   

讓一個線程等待另一個線程完成才繼續執行。如A線程線程執行體中調用B線程的join()方法,則A線程被阻塞,知道B線程執行完爲止,A才能得以繼續執行。

 

線程同步

線程安全問題

todo

synchronized

對共享資源進行訪問的方法定義中加上synchronized關鍵字修飾,使得此方法稱爲同步方法。可以簡單理解成對此方法進行了加鎖,其鎖對象爲當前方法所在的對象自身。多線程環境下,當執行此方法時,首先都要獲得此同步鎖(且同時最多隻有一個線程能夠獲得),只有當線程執行完此同步方法後,纔會釋放鎖對象,其他的線程纔有可能獲取此同步鎖,以此類推...

 

block

 

 

線程通信

傳統

wait()/notify()/notifyAll()

在博文《Java總結篇系列:java.lang.Object》中有提及到這三個方法,雖然這三個方法主要都是用於多線程中,但實際上都是Object類中的本地方法。因此,理論上,任何Object對象都可以作爲這三個方法的主調,在實際的多線程編程中,只有同步鎖對象調這三個方法,才能完成對多線程間的線程通信。

wait():導致當前線程等待並使其進入到等待阻塞狀態。直到其他線程調用該同步鎖對象的notify()或notifyAll()方法來喚醒此線程。

notify():喚醒在此同步鎖對象上等待的單個線程,如果有多個線程都在此同步鎖對象上等待,則會任意選擇其中某個線程進行喚醒操作,只有當前線程放棄對同步鎖對象的鎖定,纔可能執行被喚醒的線程。

notifyAll():喚醒在此同步鎖對象上等待的所有線程,只有當前線程放棄對同步鎖對象的鎖定,纔可能執行被喚醒的線程。

 

condition

todo

 

阻塞隊列

todo

 

線程池

todo

 

threadLocal

 

todo

 

參考文章

https://blog.csdn.net/liaobairen/article/details/82764604

Java總結篇系列:java.lang.Object

瘋狂java講義

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章