1. 程式人生 > >【搞定Java併發程式設計】第1篇:執行緒的五種可用狀態

【搞定Java併發程式設計】第1篇:執行緒的五種可用狀態

本文轉載自牛客網上一網友的回答:概括的解釋下執行緒的幾種可用狀態

第一種狀態:新建(new)新建了一個執行緒物件。例如,Thread thread = new Thread();

第二種狀態:可執行狀態(Runnable)又叫“就緒狀態”。執行緒新建後,其他執行緒(比如main執行緒)呼叫了該物件的start()方法,從而來啟動該執行緒。Runnable狀態的執行緒位於可執行執行緒池中,等待被執行緒排程選中,獲取CPU的使用權;

第三種狀態:執行狀態(Running)可執行狀態(Runnable)的執行緒獲得了CPU時間片(timeslice),執行程式碼。需要注意的是,執行緒只能從就緒狀態進入到執行狀態;

第四種狀態:阻塞狀態(Block)阻塞狀態是指執行緒因為某種原因放棄了CPU使用權,即讓出了CPU TimeSlice,暫時停止執行。直到執行緒重新進入可執行(Runnable)狀態,才有機會再次獲得CPU TimeSlice轉到執行(Running)狀態。阻塞的情況有三種:

1、等待阻塞:執行(Running)的執行緒執行wait()方法,JVM會把該執行緒放入等待佇列(waiting  queue)中;

2、同步阻塞:執行(Running)的執行緒在獲取物件的同步鎖時,若該同步鎖被別的執行緒佔用,則JVM會把該執行緒先放入鎖池(lock  pool)中;

3、其他阻塞:執行(RunnIng)的執行緒執行Thread.sleep()方法或者t.join()方法,或者發出I/O請求時,JVM會把該執行緒置為阻塞狀態。當sleep()狀態超時時、join()等待執行緒終止或者超時、或者I/O處理完畢時,執行緒重新轉入可執行(Runnable)狀態。

第五種狀態:死亡(Dead):執行緒run()方法和main()方法執行結束、或者因異常退出了run()方法,則該執行緒結束生命週期。死亡的執行緒是不可再次重生的。


另一位牛友的比喻回答:

可以用早起坐地鐵來比喻這個過程:

還沒起床:sleeping

起床收拾好了,隨時可以坐地鐵出發:Runnable

等地鐵來:Waiting

地鐵來了,但要排隊上地鐵:I/O阻塞

上了地鐵,發現暫時沒座位:synchronized阻塞

地鐵上找到座位:Running

到達目的地:Dead


比較重要的幾點需要注意:

1 sleep和yield的區別在於, sleep可以使優先順序低的執行緒得到執行的機會,  而yield只能使同優先順序的執行緒有執行的機會;

2 interrupt方法不會中斷一個正在執行的執行緒.就是指執行緒如果正在執行的過程中, 去呼叫此方法是沒有任何反應的. 為什麼呢, 因為這個方法只是提供給 被阻塞的執行緒, 即當執行緒呼叫了.Object.wait, Thread.join, Thread.sleep三種方法之一的時候, 再呼叫interrupt方法, 才可以中斷剛才的阻塞而繼續去執行執行緒;

3 join()  當join(0)時等待一個執行緒執行直到它死亡返回主執行緒,  當join(1000)時主執行緒等待一個執行緒1000納秒,後回到主執行緒繼續執行;

4 waite()和notify()必須在synchronized函式或synchronized  block中進行呼叫。如果在non-synchronized函式或non-synchronized  block中進行呼叫,雖然能編譯通過,但在執行時會發生IllegalMonitorStateException的異常。


這5種狀態涉及到的內容包括Object類, Thread和synchronized關鍵字。

Object類,定義了wait(), notify(), notifyAll()等休眠/喚醒函式。

Thread類,定義了一些列的執行緒操作函式。例如,sleep()休眠函式, interrupt()中斷函式, getName()獲取執行緒名稱等。

synchronized,是關鍵字;它區分為synchronized程式碼塊和synchronized方法。synchronized的作用是讓執行緒獲取物件的同步鎖。

在後面詳細介紹wait(),notify()等方法時,我們會分析為什麼“wait(), notify()等方法要定義在Object類,而不是Thread類中”。


參考及推薦

1、牛客網:概括的解釋下執行緒的幾種可用狀態

2、Java多執行緒系列--“基礎篇”01之 基本概念http://www.cnblogs.com/skywang12345/p/3479024.html