java中wait()、this.wait()、super.wait()、object.wait()的使用區別
阿新 • • 發佈:2019-01-02
今天有位同學過來問我下面程式碼中那個super.wait()是什麼意思?
public synchronized void waitAvailable() {
try {
if (num == "wait")
super.wait();
} catch (InterruptedException ex) {
}
}
那我們今天就來講一下synchronized關鍵字中條件物件的使用吧
(1) 執行緒持有當前物件的鎖的結構
我們知道wait()\notify()\notifyAll() 方法都是java.lang.Object類的 native方法,如果我們要在某個執行緒中的synchronized塊中呼叫 wait()\notify()\notifyAll() 這幾個方法,public synchronized void waitAvailable() { } public void waitAvailable() { synchronized(this) { } }
有且只能呼叫執行緒所持有的那個鎖的物件的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)