1. 程式人生 > >java中wait()、this.wait()、super.wait()、object.wait()的使用區別

java中wait()、this.wait()、super.wait()、object.wait()的使用區別

今天有位同學過來問我下面程式碼中那個super.wait()是什麼意思?

	public synchronized void waitAvailable() {
		try {
			if (num == "wait")
			    super.wait();
		} catch (InterruptedException ex) {
		}
	}
那我們今天就來講一下synchronized關鍵字中條件物件的使用吧

(1) 執行緒持有當前物件的鎖的結構

	public synchronized void waitAvailable() {

	}
	
	public void waitAvailable() {
		synchronized(this) {
			
		}
	}
我們知道wait()\notify()\notifyAll() 方法都是java.lang.Object類的 native方法,如果我們要在某個執行緒中的synchronized塊中呼叫 wait()\notify()\notifyAll() 這幾個方法,

有且只能呼叫執行緒所持有的那個鎖的物件的wait()\notify()\notifyAll()方法。如果當前執行緒不是物件鎖的持有者,則持有鎖的方法就會丟擲一個java.lang.IllegalMonitorStateException異常。

我們來看如下的程式碼例項:

public class Method {
	private int num = 10;
	
//	private Object lock = new Object();
	
	// 當前執行緒吃用當前物件的所
	public synchronized void method() {
	
		if (num > 8) {
			for (int i = 0; i<3 ;i++) {
				System.out.println(Thread.currentThread().getName() + " : " + num);
				num--;
			}
			try {
				System.out.println(Thread.currentThread().getName() + " wait begin ");
				//呼叫父類Object的native方法wait()
//				super.wait();
//			    this.wait();
     			wait();
				System.out.println(Thread.currentThread().getName() + " wait end ");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} 
		
		if (num <=7 && num > 1) {
			for (int i = 0; i<7 ;i++) {
				System.out.println(Thread.currentThread().getName() + " : " + num);
				num--;
			}
			//呼叫父類Object的native方法wait()
//			super.notify();
//			this.notify();		
			notify();
			System.out.println(Thread.currentThread().getName() + " notify ");
		}	
	}
	
	public static void main(String [] args) {
		final Method m = new Method();
		Thread t1= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"A");
		
		Thread t2= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"B");
		t1.start();
		t2.start();
	}
}

java 中任何類都是從java.lang.Object類的子類,那麼任何類就繼承了java.lang.Object類的公有的wait()\notify()\notifyAll() 這幾個native方法。

若執行緒持有的是當前物件的鎖 那麼直接呼叫wait()、super.wait()、this.wait(),都是直接呼叫的當前物件的方法。所以在此處程式碼中呼叫wait()\notify()、super.wait()\super.notify、this.wait()\this.notify是一樣的。

(2) 執行緒持有顯示鎖的結構

	private Object lock = new Object();
	
	public void method () {
		synchronized(lock) {
			
		}
	}

我們直接上程式碼:
public class Method {
	private int num = 10;
	
	private Object lock = new Object();
	

	public synchronized void method() {
		// 當前執行緒持有物件lock的鎖 那麼下面應用條件物件時就必須呼叫鎖的相應的方法
		synchronized(lock) {
			if (num > 8) {
				for (int i = 0; i<3 ;i++) {
					System.out.println(Thread.currentThread().getName() + " : " + num);
					num--;
				}
				try {
					System.out.println(Thread.currentThread().getName() + " wait begin ");
					//呼叫父類Object的native方法wait()
//				super.wait();
//			    this.wait();
//     			wait();
					// 呼叫顯示鎖lock的wait()方法
					lock.wait();
					System.out.println(Thread.currentThread().getName() + " wait end ");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} 
			
			if (num <=7 && num > 1) {
				for (int i = 0; i<7 ;i++) {
					System.out.println(Thread.currentThread().getName() + " : " + num);
					num--;
				}
				//呼叫父類Object的native方法wait()
//			super.notify();
//			this.notify();		
//			notify();
				// 呼叫顯示鎖lock的notify()方法
				lock.notify();
				System.out.println(Thread.currentThread().getName() + " notify ");
			}	
		}
	
	}
	
	public static void main(String [] args) {
		final Method m = new Method();
		Thread t1= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"A");
		
		Thread t2= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"B");
		t1.start();
		t2.start();
	}
}

上例中 我們讓當前執行緒持有的是lock物件的鎖,那麼在使用條件物件時就必須呼叫當前鎖lock物件的 wait()\notify()\notifyAll()方法。當然這些方法也是從java.lang.Object類繼承而來。

如果當前執行緒持有的是物件A的鎖,而使用條件物件時呼叫的是物件B的wait()\notify()方法組合,那麼就會丟擲一個java.lang.IllegalMonitorStateException異常

程式碼如下:

public class Method {
	private int num = 10;
	
	private Object lock = new Object();
	

	public synchronized void method() {
		// 當前執行緒持有當前物件this的鎖
		synchronized(this) {
			if (num > 8) {
				for (int i = 0; i<3 ;i++) {
					System.out.println(Thread.currentThread().getName() + " : " + num);
					num--;
				}
				try {
					System.out.println(Thread.currentThread().getName() + " wait begin ");
					//呼叫父類Object的native方法wait()
//				super.wait();
//			    this.wait();
//     			wait();
					// 使用條件物件時 呼叫顯示鎖lock的wait()方法  這樣就會丟擲異常
					lock.wait();
					System.out.println(Thread.currentThread().getName() + " wait end ");
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} 
			
			if (num <=7 && num > 1) {
				for (int i = 0; i<7 ;i++) {
					System.out.println(Thread.currentThread().getName() + " : " + num);
					num--;
				}
				//呼叫父類Object的native方法wait()
//			super.notify();
//			this.notify();		
//			notify();
				// 使用條件物件時 呼叫顯示鎖lock的notify()方法  這樣就會丟擲異常
				lock.notify();
				System.out.println(Thread.currentThread().getName() + " notify ");
			}	
		}
	
	}
	
	public static void main(String [] args) {
		final Method m = new Method();
		Thread t1= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"A");
		
		Thread t2= new Thread(new Runnable() {
			public void run() {
				m.method();
			}
		},"B");
		t1.start();
		t2.start();
	}
}

輸出結果:
A : 10
A : 9
A : 8
A wait begin 
B : 7
B : 6
B : 5
B : 4
B : 3
B : 2
B : 1
Exception in thread "A" java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:485)
	at com.renren.testwait.Method.method(Method.java:24)
	at com.renren.testwait.Method$1.run(Method.java:53)
	at java.lang.Thread.run(Thread.java:662)
Exception in thread "B" java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at com.renren.testwait.Method.method(Method.java:42)
	at com.renren.testwait.Method$2.run(Method.java:59)
	at java.lang.Thread.run(Thread.java:662)