java多線程基礎必備——線程的生命週期及5種狀態

總覽

Java線程具有五中基本狀態

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

就緒狀態(Runnable):當調用線程對象的start()方法(t.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()中的線程也不會執行。因此sleep()方法常用來暫停線程執行。

 

join   

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

 

wait()/notify()/notifyAll()

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

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

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

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

 

synchronized

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

 

 

參考文章

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

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

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