這里使用“通知”這個詞,而不用“通信”這個詞,是為了避免詞義的擴大化。
線程之間的通知,通過Object對象的wait()和notify() 或notifyAll() 方法實現。
下面用一個例子,來說明其工作原理:
假設有兩個線程,A和B。共同擁有一個同步對象,lock。
1.首先,線程A通過synchronized(lock) 獲得lock同步對象,然后調用lock.wait()函數,放棄lock同步對象,線程A停止運行,進入等待隊列。
2.線程B通過synchronized(lock) 獲得線程A放棄的lock同步對象,做完一定的處理,然后調用 lock.notify() 或者lock.notifyAll() 通知等待隊列里面的線程A。
3.線程A從等待隊列里面出來,進入ready隊列,等待調度。
4.線程B繼續處理,出了synchronized(lock)塊之后,放棄lock同步對象。
5.線程A獲得lock同步對象,繼續運行。
例子代碼如下:
public class SharedResource implements Runnable{
Object lock = new Object();
public void run(){
// 獲取當前線程的名稱。
String threadName = Thread.currentThread().getName();
if( “A”.equals(threadName)){
synchronized(lock){ //線程A通過synchronized(lock) 獲得lock同步對象
try{
System.out.println(“ A gives up lock.”);
lock.wait(); // 調用lock.wait()函數,放棄lock同步對象,
// 線程A停止運行,進入等待隊列。
}catch(InterruptedException e){
}
// 線程A重新獲得lock同步對象之后,繼續運行。
System.out.println(“ A got lock again and continue to run.”);
} // end of synchronized(lock)
}
if( “B”.equals(threadName)){
synchronized(lock){//線程B通過synchronized(lock) 獲得線程A放棄的lock同步對象
System.out.println(“B got lock.”);
lock.notify(); //通知等待隊列里面的線程A,進入ready隊列,等待調度。
//線程B繼續處理,出了synchronized(lock)塊之后,放棄lock同步對象。
System.out.println(“B gives up lock.”);
} // end of synchronized(lock)
boolean hasLock = Thread.holdsLock(lock); // 檢查B是否擁有lock同步對象。
System.out.println(“B has lock ? -- ” +hasLock); // false.
}
}
}
public class TestMain{
public static void main(){
Runnable resource = new SharedResource();
Thread A = new Thread(resource,”A”);
A.start();
// 強迫主線程停止運行,以便線程A開始運行。
try {
Thread.sleep(500);
}catch(InterruptedException e){
}
Thread B = new Thread(resource,”B”);
B.start();
}
}