public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}
如上例,如果wait()
先阻塞enter,ThreadB中后续的notify()
会告诉Main Thread继续。
但是我们不能保证wait()
会在notify(
)之前执行,如果ThreadB先进入block呢? Notify()
将在 wait()
之前执行,因此 wait()
将永远卡在那里(因为不再有 notify()
告诉它继续)?处理此问题的正确方法通常是什么?
最佳答案
你应该几乎总是有一个谓词和等待/通知。也就是说,你需要一个条件 您可以检查的内容,例如变量变为真、队列变为空/满等。只是盲目地等待某人调用 .notify() 的用例很少。
所以,以下是不正确的,因为你说的原因,另一个线程可以在 ThreadA 调用 .wait() 之前调用 .notify()
public class ThreadA {
public static Object latch = new Object();
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(latch ) {
latch.wait(); //wait for B to finish a calculation
}
System.out.println("Total is: " + b.total);
}
}
class ThreadB extends Thread {
int total;
@Override
public void run() {
for (int i = 0; i < 100; i++) {
total += i;
}
synchronized(ThreadA.latch) {
ThreadA.latch.notify();
}
}
}
你需要做这样的事情:
public class ThreadA {
public static Object latch = new Object();
public static boolean done = false;
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
synchronized(latch ) {
while (!done) { //wait for B to indicate it is finished.
latch.wait();
}
}
System.out.println("Total is: " + b.total);
}
}
class ThreadB extends Thread {
int total;
@Override
public void run() {
for (int i = 0; i < 100; i++) {
total += i;
}
synchronized(ThreadA.latch) {
ThreadA.done = true;
ThreadA.latch.notify();
}
}
}
请注意,在上面,done
变量受同步块(synchronized block)保护,.wait()
将自动释放/重新获取该锁。所以没有竞争条件,如果在我们到达 .wait()
调用之前调用了 .notify(),ThreadA 会发现,因为 done
将是 true
并且根本不进入 .wait()
调用。
对于像这段代码这样的简单情况,您可以等待 ThreadB 结束,可以使用 b.join();
关于Java notify() 在 wait() 之前运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19537636/