在使用wait/notify机制实现多线程通信时,需要注意如下方面:
- notify只能通知一个线程,如果有多个线程需要被通知的话,需要使用notifyAll。
- notify不能通知过早,如果通知过早,会导致wait线程一直等待。
先看等待线程类:
package com.lenovo.plm.dms.p11;
public class MyThreadA extends Thread {
private Object lock;
public MyThreadA(Object lock){
this.lock = lock;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
synchronized(lock){
System.out.println(Thread.currentThread().getName() +" begin to wait..");
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +" come to end..");
}
}
}
再看通知线程类:
package com.lenovo.plm.dms.p11;
public class MyThreadB extends Thread {
private Object lock;
public MyThreadB(Object lock){
this.lock = lock;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
synchronized(lock){
System.out.println(Thread.currentThread().getName() +" begin to notify..");
lock.notify();
System.out.println(Thread.currentThread().getName() +" end to notify..");
}
}
}
运行类如下:
package com.lenovo.plm.dms.p11;
public class Main {
public static void main(String[] args) {
Object lock = new Object();
MyThreadA t1 = new MyThreadA(lock);
MyThreadA t2 = new MyThreadA(lock);
t1.start();
t2.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MyThreadB t3 = new MyThreadB(lock);
t3.start();
}
}
此处创建了两个等待线程,一个通知线程,当通知线程调用notify后,只有一个等待线程被通知到了。看结果:
Thread-0 begin to wait..
Thread-1 begin to wait..
Thread-2 begin to notify..
Thread-2 end to notify..
Thread-0 come to end..
Thread-1 begin to wait..
Thread-2 begin to notify..
Thread-2 end to notify..
Thread-0 come to end..
这里有一个线程Thread-1还在等待中。将通知线程中的notify方法改为notifyAll方法后,运行结果如下:
Thread-0 begin to wait..
Thread-1 begin to wait..
Thread-2 begin to notify..
Thread-2 end to notify..
Thread-1 come to end..
Thread-0 come to end..
Thread-1 begin to wait..
Thread-2 begin to notify..
Thread-2 end to notify..
Thread-1 come to end..
Thread-0 come to end..
还有一种情况是:如果通知线程在其他线程等待之前就通知了,那么等待的线程就一直会等待着,不会停止了。
现在将运行类的main方法改成如下样子:
package com.lenovo.plm.dms.p11;
public class Main {
public static void main(String[] args) {
Object lock = new Object();
MyThreadA t1 = new MyThreadA(lock);
MyThreadA t2 = new MyThreadA(lock);
MyThreadB t3 = new MyThreadB(lock);
t1.start();
t2.start();
t3.start();
}
}
运行结果如下:
Thread-0 begin to wait..
Thread-2 begin to notify..
Thread-2 end to notify..
Thread-1 begin to wait..
Thread-0 come to end..
Thread-2 begin to notify..
Thread-2 end to notify..
Thread-1 begin to wait..
Thread-0 come to end..
这里每次运行结果都会不同,这一次运行,Thread-1还没开始等待,Thread-2就通知了,导致Thread-1一直等待。