Java中wait與notify方法的使用

在java多線程編程中,最被經常用到的便是wait與notfiy方法,這兩個方法可以用來更加精確地控制被同步的代碼,從而使得被同步的代碼最小化,提高併發效率。
當某個類的某個方法被標記爲synchronized時,這個方法在同一時間只能被一個線程訪問。此時這個方法中的所有代碼都是被同步的,只有當一個線程執行完所有的代碼之後,下一個線程才能開始執行。當被同步的方法代碼量比較小,而且每一步執行都非常快的時候僅僅使用synchronized關鍵字就夠了。但是,如果被同步的方法裏面有一些代碼是可以被共享的,而且這些能夠被共享的代碼裏面存在比較耗時的操作時,僅僅使用synchronized關鍵字就無法達到最高的效率,這個時候可以使用wait與notify方法來對併發訪問做更進一步的控制。首先看兩段代碼:

public class TestThread {
private boolean isIdle = true;

public synchronized void work(){
/*
* Some work which can be shared
*/
try {
/*
* to check if we can have this object's monitor
*/
if(!isIdle){
System.out.println(Thread.currentThread().toString() + ":I'm waiting....");
}
while(!isIdle){
wait();
}

/*
* to set isIdle to false, I'm working....
*/
this.isIdle = false;
System.out.println(Thread.currentThread().toString() + ":I'm working....");
Thread.currentThread().sleep(1000);
System.out.println(Thread.currentThread().toString() + ":I'm finished....");

/*
* to notify all other thread which is waiting for this object's monitor
*/
this.isIdle = true;
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

在上面的類中定義了一個方法work,在這個方法中的try塊之前可以執行一些可共享的代碼,而try塊中的代碼是不能夠被共享的。因此,我們在進入try之後會首先判斷標誌isIdle是否爲true,如果爲true就表示當前沒有其他線程正在訪問,因此當前線程就獲得了執行try塊中代碼的權利。在執行代碼前當前線程會將isIdle設置成false,這樣當其他線程進入try,之後就會發現isIdle爲false,從而進入等待狀態。
當一個線程執行完try中的代碼之後,會將isIdle重新設置爲true,同是使用notifyAll方法通知所有等待獲得執行try塊中代碼的權利的線程。
下面這個類用來測試上面的TestThread:

public class ThreadTester {
private static TestThread tt = new TestThread();

public static void main(String[] args){
for(int i = 0; i < 5; i++){
new Thread(new Runnable(){
public void run(){
tt.work();
}
}).start();
}
}
}

這個類在main方法中啓動了五個不同的線程來訪問TestThread的work方法,從打印的結果中可以看出,每次線程的執行順序都會有些許的差別。
日誌:
第一次運行:

Thread[Thread-0,5,main]:I'm working....
Thread[Thread-0,5,main]:I'm finished....
Thread[Thread-1,5,main]:I'm working....
Thread[Thread-1,5,main]:I'm finished....
Thread[Thread-3,5,main]:I'm working....
Thread[Thread-3,5,main]:I'm finished....
Thread[Thread-2,5,main]:I'm working....
Thread[Thread-2,5,main]:I'm finished....
Thread[Thread-4,5,main]:I'm working....
Thread[Thread-4,5,main]:I'm finished....

第二次運行:

Thread[Thread-0,5,main]:I'm working....
Thread[Thread-0,5,main]:I'm finished....
Thread[Thread-2,5,main]:I'm working....
Thread[Thread-2,5,main]:I'm finished....
Thread[Thread-1,5,main]:I'm working....
Thread[Thread-1,5,main]:I'm finished....
Thread[Thread-4,5,main]:I'm working....
Thread[Thread-4,5,main]:I'm finished....
Thread[Thread-3,5,main]:I'm working....
Thread[Thread-3,5,main]:I'm finished....
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章