1. 程式人生 > >Java多執行緒-51-兩個執行緒之間的通訊

Java多執行緒-51-兩個執行緒之間的通訊

這篇來學習Object類下兩個方法,分別是wait()和notify(), 這兩個方法是在多執行緒中設定執行緒等待和喚醒執行緒的作用。這篇,通過兩個執行緒的例子來學習wait()執行緒等待方法和notify()喚醒執行緒方法。

1.兩個執行緒,列印兩句話。

前面文章,有類似下面的程式碼,兩個執行緒隨機列印兩句話。

package thread;

public class Notify_Demo {

	public static void main(String[] args) {
		printer p = new printer();
		new Thread() {
			public void run() {
				while(true) {
					p.printer1();
				}
			}
		}.start();
		
		new Thread() {
			public void run() {
				while(true) {
					p.printer2();
				}
			}
		}.start();
	}

}

class printer {
	
	public void printer1() {
		System.out.print("跟");
		System.out.print("我");
		System.out.print("一");
		System.out.print("起");
		System.out.println("念");
	}
	
	public void printer2() {
		synchronized (printer.class) {
			System.out.print("做");
			System.out.print("測");
			System.out.print("試");
			System.out.print("死");
			System.out.print("路");
			System.out.print("一");
			System.out.println("條");
		}
	}
}

這個執行的效果是,先隨機列印N個重複的“跟我一起念”,然後隨機重複列印N個“做測試死路一條”。 

那麼,如果我們現在需要,先列印一遍“跟我一起念”,然後裡面跟著列印一遍“做測試死路一條”。這個要怎麼做呢?這個時候就要用到Object類下的wait()和notify()方法。

大概程式碼實現的場景是這樣的,執行緒A先列印“跟我一起念”一遍,執行緒A進入等待,這個時候需要用wait()方法,然後執行緒B啟動區列印“做測試死路一條”,為什麼會啟動呢,這裡就需要用到notify()喚醒執行緒的功能,然後執行緒B等待,喚醒執行緒A,這樣迴圈下去。

實現程式碼如下

package thread;

public class Notify_Demo {

	public static void main(String[] args) {
		printer p = new printer();
		new Thread() {
			public void run() {
				while(true) {
					try {
						p.printer1();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
		
		new Thread() {
			public void run() {
				while(true) {
					try {
						p.printer2();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
	}

}

class printer {
	private int flag = 1;
	public void printer1() throws InterruptedException {
		synchronized (this) {
			if(flag != 1) {
				this.wait();  // 設定執行緒等待,如果flag 不等於1
			}
			System.out.print("跟");
			System.out.print("我");
			System.out.print("一");
			System.out.print("起");
			System.out.println("念");
			flag = 2;
			this.notify(); // 設定flag等於2,使用執行緒喚醒功能,其他執行緒就可以啟動
		}
	}
	
	public void printer2() throws InterruptedException {
		synchronized (this) {
			if(flag != 2) {
				this.wait();  // 設定執行緒等待,如果flag 不等於2
			}
			System.out.print("做");
			System.out.print("測");
			System.out.print("試");
			System.out.print("死");
			System.out.print("路");
			System.out.print("一");
			System.out.println("條");
			flag = 1;
			this.notify();  //隨機喚醒單個等待的執行緒
		}
	}
}

執行效果

跟我一起念
做測試死路一條
跟我一起念
做測試死路一條
跟我一起念
做測試死路一條
跟我一起念
做測試死路一條
...

上面就是兩個執行緒之間的通訊過程,執行緒A執行,執行緒B等待,執行緒B等待喚醒執行緒A,這樣迴圈。