Java多線程學習:wait與notify方法的使用

  在java多線程編程中,最被常常用到的即是wait與notfiy方法,這兩個方法能夠用來更加精確地控制被同步的代碼,從而使得被同步的代碼最小化,提升併發效率。 php

  當某個類的某個方法被標記爲synchronized時,這個方法在同一時間只能被一個線程訪問。此時這個方法中的全部代碼都是被同步的,只有當一個線程執行完全部的代碼以後,下一個線程才能開始執行。當被同步的方法代碼量比較小,並且每一步執行都很是快的時候僅僅使用synchronized關鍵字就夠了。可是,若是被同步的方法裏面有一些代碼是能夠被共享的,並且這些可以被共享的代碼裏面存在比較耗時的操做時,僅僅使用synchronized關鍵字就沒法達到最高的效率,這個時候可使用wait與notify方法來對併發訪問作更進一步的控制。首先看兩段代碼: html

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: java

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....

 

推薦閱讀:高併發

  Thread類的sleep()方法和對象的wait()方法均可以讓線程暫停執行,它們有什麼區別?測試

  線程同步之wait和notify方法this

  最簡實例說明WAIT、NOTIFY、NOTIFYALL的使用方法.net

  Thread_wait、notify、notifyAll的使用方法

相關文章
相關標籤/搜索