首先了解一下什麼是線程的狀態,線程狀態就是當線程被建立(new),而且啓動(start)後,它不是一啓動就進入了執行狀態(run),也不是一直都處於執行狀態。多線程
這裏說一下Java 的Thread類裏面有一個State方法,這個方法裏面涵蓋了6種線程的狀態,以下:併發
public enum State { // 還沒有啓動的線程的線程狀態。 NEW, // 可運行線程的線程狀態。 RUNNABLE, // 線程的線程狀態被阻塞,等待監視器鎖定。 BLOCKED, // 等待線程的線程狀態。 WAITING, // 具備指定等待時間的等待線程的線程狀態。 TIMED_WAITING, // 終止線程的線程狀態。 TERMINATED; }
線程剛被建立,不過尚未被啓動(尚未調用start方法)ide
處於可運行狀態的線程正在Java虛擬機中執行,可是它可能正在等待來自操做系統(例如處理器)的其餘資源。spa
當一個線程想獲取一個對象鎖,不過該對象鎖被其它的線程持有時,該線程就會進入鎖阻塞狀態;當該線程持有鎖的時候,該線程將會變成可運行的狀態。操作系統
當一個線程在等待另外一個線程執行一個(喚醒)動做時,該線程就會進入無限等待狀態。進入這個狀態後是不能自動喚醒的,要等待另外一個線程調用notify()方法,或notifyall()方法纔可以被喚醒。線程
相似於無限等待狀態,有幾個方法有超時參數,如:Thread.sleep、Object.wait方法。調用這些方法,進入計時等待狀態。計時等待狀態將會一直保持到超時期滿或者接收到喚醒通知。code
一、由於run方法的正常退出而死亡。
二、由於沒有捕獲的異常,終止了run方法而死亡。對象
顧客要去飯店吃飯,自助下單,說明要吃什麼,數量是多少。下完單之後,顧客就等待該飯店廚師作飯菜,也就是Waiting狀態(無限等待狀態)。blog
廚師收到下單信息,開始作飯菜,作好飯菜,把飯菜遞到顧客桌面上,顧客看到飯菜已經來了(notify方法),就能夠開吃了(等待喚醒機制)。資源
建立一個顧客線程:下單,告知廚師要什麼菜,菜的數量,調用wait方法,放棄CPU的執行,進入到無限等待狀態(Waiting)
建立一個廚師線程:看到下單,花了3秒鐘作飯菜,作好以後,調用notify方法,喚醒顧客吃飯了。
顧客線程和廚師線程,必須使用同步代碼塊包裹起來,保證等待和喚醒只能有一個在執行。
同步使用的鎖對象必須保證惟一。
只有鎖對象纔可以調用Object.wait方法和Object.notify方法。
public class Demo01WaitNotify { public static void main(String[] args) { // 建立鎖對象(要保證鎖惟一) Object object = new Object(); // 建立一個顧客線程 new Thread() { @Override public void run() { // 使用同步代碼塊包裹起來,保證等待和喚醒只能有一個在執行。 synchronized (object) { // 顧客下單 System.out.println("我要一個西虹市炒番茄,一個馬鈴薯炒土豆,兩碗米飯"); // 調用wait方法,放棄CPU的執行,進入到無限等待狀態(Waiting) try { object.wait(); } catch (InterruptedException e) { e.printStackTrace(); } // 喚醒以後(飯菜上來後),吃飯!!!真香。 System.out.println("我就是餓死,從這裏跳下去,也不會吃大家一口飯。。。真香!!!!"); } } }.start(); // 建立一個廚師線程 new Thread() { @Override public void run() { // 廚師收到下單請求,花三秒鐘把飯菜作好 try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } // 使用同步代碼塊包裹起來,保證等待和喚醒只能有一個在執行。 synchronized (object) { System.out.println("個人飯菜三秒鐘作好了,你食唔食哦?"); // 作好以後,調用notify方法,喚醒顧客吃飯了。 object.notify(); } } }.start(); } }
控制檯輸出:
我要一個西虹市炒番茄,一個馬鈴薯炒土豆,兩碗米飯
個人飯菜三秒鐘作好了,你食唔食哦?
我就是餓死,從這裏跳下去,也不會吃大家一口飯。。。真香!!!!
上面的代碼,存在線程間的通訊,那什麼又是線程間的通訊呢?簡單的說,就是多個線程在處理同一個資源,可是處理的動做(線程的任務)卻不一樣。如上,廚師線程作飯菜,顧客線程吃飯菜。那爲何要進行線程間的通訊呢?多個線程併發執行的時候,在默認狀況下CPU是隨機切換線程的,當咱們須要多個線程來共同完成一件任務,而且但願它們有規律的執行的時候,那麼多線程就之間就須要一些協調通訊,來達到多線程共同操做一份數據。
對代碼中通訊的理解:
對又沒有飯菜進行判斷——
一、沒有飯菜(False)。
二、顧客下單。
三、廚師作飯菜。
四、顧客線程等待。
五、廚師作好飯菜
六、修改飯菜的狀態(True)
七、有飯菜,廚師線程提醒顧客線程吃飯菜。
八、廚師線程等待
九、吃完飯菜,修改飯菜的狀態(False)
這就是顧客線程與廚師線程之間的通訊。以此類推,其它Java程序中多線程的通訊也是一樣的道理。