C 之多執行緒學習篇(3)之執行緒狀態

2021-08-21 13:19:45 字數 3297 閱讀 2511

1. 執行緒的幾種狀態

執行緒在一定條件下,狀態會發生變化。執行緒一共有以下幾種狀態:

1、新建狀態(new):新建立了乙個執行緒物件。

2、就緒狀態(runnable):執行緒物件建立後,其他執行緒呼叫了該物件的start()方法。該狀態的執行緒位於「可執行執行緒池」中,變得可執行,只等待獲取cpu的使用權即在就緒狀態的程序除cpu之外,其它的執行所需資源都已全部獲得。

3、執行狀態(running):就緒狀態的執行緒獲取了cpu,執行程式**。

4、阻塞狀態(blocked):阻塞狀態是執行緒因為某種原因放棄cpu使用權,暫時停止執行。直到執行緒進入就緒狀態,才有機會轉到執行狀態。

阻塞的情況分三種:

(1)、等待阻塞:執行的執行緒執行wait()方法,該執行緒會釋放占用的所有資源,jvm會把該執行緒放入「等待池」中。進入這個狀態後,是不能自動喚醒的,必須依靠其他執行緒呼叫notify()或notifyall()方法才能被喚醒,喚醒後進入「鎖池」中,通過獲取鎖狀態來判斷是否進入就緒狀態

(2)、同步阻塞:執行的執行緒在獲取物件的同步鎖時,若該同步鎖被別的執行緒占用,則jvm會把該執行緒放入「鎖池」中。

(3)、其他阻塞:執行的執行緒執行sleep()或join()方法,或者發出了i/o請求時,jvm會把該執行緒置為阻塞狀態。當sleep()狀態超時、join()等待執行緒終止或者超時、或者i/o處理完畢時,執行緒重新轉入就緒狀態。

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

執行緒變換的狀態轉化圖如下:

注:拿到物件的鎖標記,即為獲得了對該物件(臨界區)的使用許可權。即該執行緒獲得了執行所需的資源,進入「就緒狀態」,只需獲得cpu,就可以執行。因為當呼叫wait()後,執行緒會釋放掉它所占有的「鎖標誌」,所以執行緒只有在此獲取資源才能進入就緒狀態。

下面小小的作下解釋:

1、執行緒的實現有兩種方式,一是繼承thread類,二是實現runnable介面,但不管怎樣,  當我們new了這個物件後,執行緒就進入了初始狀態; 

2、當該物件呼叫了start()方法,就進入就緒狀態; 

3、進入就緒後,當該物件被作業系統選中,獲得cpu時間片就會進入執行狀態; 

4、進入執行狀態後情況就比較複雜了 

4.1、run()方法或main()方法結束後,執行緒就進入終止狀態; 

4.2、當執行緒呼叫了自身的sleep()方法或其他執行緒的join()方法,程序讓出cpu,然後就會進入阻塞狀態(該狀態既停止當前執行緒,但並不釋放所占有的資源即呼叫sleep ()函式後,執行緒不會釋放它的「鎖標誌」。)。當sleep()結束或join()結束後,該執行緒進入可執行狀態,繼續等待os分配cpu時間片。典型地,sleep()被用在等待某個資源就緒的情形:測試發現條件不滿足後,讓執行緒阻塞一段時間後重新測試,直到條件滿足為止。

4.3、執行緒呼叫了yield()方法,意思是放棄當前獲得的cpu時間片,回到就緒狀態,這時與其他程序處於同等競爭狀態,os有可能會接著又讓這個程序進入執行狀態; 呼叫 yield() 的效果等價於排程程式認為該執行緒已執行了足夠的時間片從而需要轉到另乙個執行緒。yield()只是使當前執行緒重新回到可執行狀態,所以執行yield()的執行緒有可能在進入到可執行狀態後馬上又被執行。

4.4、當執行緒剛進入可執行狀態(注意,還沒執行),發現將要呼叫的資源被synchroniza(同步),獲取不到鎖標記,將會立即進入鎖池狀態,等待獲取鎖標記(這時的鎖池裡也許已經有了其他執行緒在等待獲取鎖標記,這時它們處於佇列狀態,既先到先得),一旦執行緒獲得鎖標記後,就轉入就緒狀態,等待os分配cpu時間片;

4.5.suspend()和 resume()方法:兩個方法配套使用,suspend()使得執行緒進入阻塞狀態,並且不會自動恢復,必須其對應的resume()被呼叫,才能使得執行緒重新進入可執行狀態。典型地,suspend()和 resume() 被用在等待另乙個執行緒產生的結果的情形:測試發現結果還沒有產生後,讓執行緒阻塞,另乙個執行緒產生了結果後,呼叫 resume()使其恢復。 

4.6.wait()和 notify() 方法:當執行緒呼叫wait()方法後會進入等待佇列(進入這個狀態會釋放所占有的所有資源,與阻塞狀態不同),進入這個狀態後,是不能自動喚醒的,必須依靠其他執行緒呼叫notify()或notifyall()方法才能被喚醒(由於notify()只是喚醒乙個執行緒,但我們由不能確定具體喚醒的是哪乙個執行緒,也許我們需要喚醒的執行緒不能夠被喚醒,因此在實際使用時,一般都用notifyall()方法,喚醒有所執行緒),執行緒被喚醒後會進入鎖池,等待獲取鎖標記。 

wait() 使得執行緒進入等待佇列中,它有兩種形式:

一種允許指定以毫秒為單位的一段時間作為引數;另一種沒有引數。前者當對應的 notify()被呼叫或者超出指定時間時執行緒重新進入可執行狀態即就緒狀態,後者則必須對應的 notify()被呼叫。當呼叫wait()後,執行緒會釋放掉它所占有的「鎖標誌」從而使執行緒所在物件中的其它synchronized資料可被別的執行緒使用。waite()和notify()因為會對物件的「鎖標誌」進行操作,所以它們必須在synchronized函式或synchronizedblock中進行呼叫。如果在non-synchronized函式或non-synchronizedblock中進行呼叫,雖然能編譯通過,但在執行時會發生illegalmonitorstateexception的異常。(在此處後面講進行詳細說明)

c 之多執行緒

1.對多執行緒的呼叫用到頭檔案 1.1中的操縱函式 pthread create pthread t tidp,constpthread attr t attr,void start rtn void void arg 第乙個引數為指向執行緒 識別符號的 指標。第二個引數用來設定執行緒屬性。第三個引...

Thread03之多執行緒執行緒狀態

demo 當執行緒被建立並啟動以後,它既不是一啟動就進入了執行狀態,也不是一直處於執行狀態。我們不需要去研究這幾種狀態的實現原理,我們只需知道在做執行緒操作中存在這樣的狀態。那我們怎麼去理解這幾個狀態呢,新建與被終止還是很容易理解的,我們就研究一下執行緒從runnable 可執行 狀態與非執行狀態之...

學習日記之多執行緒

要學習執行緒,首先要理解三個概念。什麼是程式,什麼是程序,什麼是執行緒。程式,是指令的集合。程序是正在執行的程式,是靜態概念。執行緒,是程序中乙個 單一的連續控制流程 也稱為輕量級程序。執行緒有一下幾個點 1.乙個程序可以擁有多個執行緒 2.乙個程序中的執行緒個共享相同的記憶體單元,即擁有相同的變兩...