1.什么是線程間通信?
多個線程在處理同一資源,但是任務卻不同。
生活中栗子:有一堆煤,有2輛車往里面送煤,有2輛車往外拉煤,這個煤就是同一資源,送煤和拉煤就是任務不同。
2.等待/喚醒機制。
涉及的方法:
(1)wait(): 讓線程處於凍結狀態,被wait的線程會被存儲到線程池(容器)中。
(2)notify():喚醒線程池中一個線程(任意).
(3)notifyAll():喚醒線程池中的所有線程。
這些方法都必須定義在同步中。
因為這些方法是用於操作線程狀態的方法。
必須要明確到底操作的是哪個鎖上的線程。
什么是線程池?
顧名思義就是事先創建若干個可執行的線程放入一個池(容器)中,需要的時候從池中獲取線程而不用自行創建,使用完畢后不需要銷毀放入池中,從而減少創建和銷毀對象的開銷。
為什么操作線程的方法wait notify notifyAll定義在了Object類中?
因為這些方法是監視器的方法。監視器其實就是鎖,就是栗子中的r。
鎖可以是任意的對象,任意的對象調用的方式一定定義在Object類中。
栗子:(誰拿鎖誰執行)
class Resource { private String name; private String sex; private boolean flag = false; public synchronized void set(String name,String sex) { if(flag)//為真的時候,就直接進入wait,這樣該線程就釋放了執行權了。為假就執行下面的語句 try{this.wait();}catch(InterruptedException e){} this.name = name; this.sex = sex; flag = true; this.notify();//喚醒輸出線程,輸出線程具備了執行資格。搶來了CPU執行權 } public synchronized void out() { if(!flag) try{this.wait();}catch(InterruptedException e){} System.out.println(name+"...+...."+sex); flag = false; notify();//喚醒輸入線程 } } //輸入 class Input implements Runnable { Resource r ; // Object obj = new Object(); Input(Resource r) { this.r = r; } public void run() { int x = 0; while(true) { if(x==0) { r.set("mike","nan"); } else { r.set("麗麗","女女女女女女"); } x = (x+1)%2; } } } //輸出 class Output implements Runnable { Resource r; // Object obj = new Object(); Output(Resource r) { this.r = r; } public void run() { while(true) { r.out(); } } } class ResourceDemo3 { public static void main(String[] args) { //創建資源。 Resource r = new Resource(); //創建任務。 Input in = new Input(r); Output out = new Output(r); //創建線程,執行路徑。 Thread t1 = new Thread(in); Thread t2 = new Thread(out); //開啟線程 t1.start(); t2.start(); } }
3.sleep()和wait()比較
(1)對於sleep()方法,我們首先要知道該方法是屬於Thread類中的。而wait()方法,則是屬於Object類中的。
(2)sleep()方法導致了程序暫停執行指定的時間,讓出cpu該其他線程,但是他的監控狀態依然保持着,當指定的時間到了又會自動恢復運行狀態。
(3)在調用sleep()方法的過程中,線程不會釋放對象鎖。
而當調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法后本線程才進入對象鎖定池准備獲取對象鎖進入運行狀態。
(4)wait可以指定時間也可以不指定時間,sleep必須指定時間。
(5)在同步中時,對cpu的執行權和鎖的處理不同。
wait:釋放執行權,釋放鎖。
sleep:釋放執行權,不釋放鎖。
栗子:
A.sleep是線程類的方法,wait是object的方法
B.sleep不釋放對象鎖,wait放棄對象鎖
C.sleep暫停線程,但監控狀態依然保持,結束后會自動恢復
D.wait進入等待鎖定池,只有針對此對象發出notify方法獲得對象鎖進入運行狀態
原因:是D中,准備獲取對象鎖進入運行狀態,而不是立即進入
4.線程狀態