1. 程式人生 > >java執行緒學習(四):執行緒等待wait()和通知notify()的詳細使用

java執行緒學習(四):執行緒等待wait()和通知notify()的詳細使用

執行緒等待wait()和通知notify(),主要用於多執行緒之間的協作,而且這兩個方法都是屬於Object類,說明任何物件都可以呼叫這兩個方法。

當在一個物件例項上呼叫wait()方法後,當前執行緒就會在這個物件上等待。直到另外的執行緒呼叫了notify()方法,出於等待的執行緒才得以繼續進行。這樣,多執行緒之間的協作就可以用這兩個方法進行通訊了。

先看下例子:

package stop_demo;

public class Wait_notify_demo {
	final static Object object=new Object();
	final static Object object2=new Object();
	public static class T1 extends Thread{
		public void run(){
			synchronized (object) {
				System.out.println(System.currentTimeMillis()+" :T1 啟動!");
				try {
					System.out.println(System.currentTimeMillis()+" :T1等待object鎖。。。。。");
					object.wait();
					System.out.println("object被喚醒。。。");
				} catch (Exception e) {
					e.printStackTrace();
				}
				System.out.println(System.currentTimeMillis()+" T1 end");

			}
		}
	}
		public static class T2 extends Thread{
			public void run(){
				synchronized (object) {
					System.out.println(System.currentTimeMillis()+" :T2 start! 隨機通知一條執行緒。");
					object.notify();//要object例項呼叫notify才行
					System.out.println(System.currentTimeMillis()+" T2 end");
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	public static void main(String[] args) {
		Thread t1=new T1();
		Thread t2=new T2();
		t1.start();
		t2.start();
	}
}

輸出結果:
在這裡插入圖片描述

可以看到,t1執行緒啟動後,進入等待狀態,t2執行緒執行,當執行object.notify()時,通知等待佇列中的執行緒啟動,也就是t1啟動,然後繼續往下執行。

多執行幾次,就會發現有時候輸出這樣的:
在這裡插入圖片描述
原因是T2先執行,結果t1執行後,執行wait方法而處於一直等待狀態,因為沒有其他執行緒去喚醒t1執行緒。

不過應該注意的是:

  • wait() 和 notify()必須配合synchrozied關鍵字使用,無論是wait()還是notify()都需要首先獲取目標物件的一個監聽器。

  • wait()會釋放鎖,而notify()不釋放鎖。

wait()會釋放鎖,而notify()不釋放鎖,這個是怎麼理解呢?其實看第一個輸出截圖就可以知道,當t1執行到wait方法時,如果t1沒有釋放鎖,那麼t2執行緒壓根就無法執行下去,說明wait()會釋放鎖,而當執行到t2中的notify時,t2會在當前執行緒往下執行,執行完了才讓t1繼續執行,說明notify方法並沒有把鎖釋放了。