Java notify()在wait()之前运行?

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()块先输入,则ThreadB中的后续notify()将告诉主线程继续。

但是我们不能保证wait()会在notify( )之前执行,如果ThreadB先进入块怎么办? Notify()将在wait()之前执行,所以wait()将永远挂起(因为没有更多的notify()告诉它继续)? 处理这个问题的正确方法通常是什么?

你应该几乎总是有一个谓词和wait / notify。 也就是说,您需要一个可以检查的条件,例如变量变为true,队列变为空/满等等。只是盲目地等待某人调用.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块保护, .wait()将自动释放/重新获取该锁。 因此没有竞争条件,并且如果在我们到达.wait()调用.wait() ,则ThreadA将发现因为done将为true而根本不进入.wait()调用。

对于像这个代码这样的简单情况,你可以等待ThreadB结束,可以用b.join();

我想你想做这样的事情

 public class ThreadA { public static void main(String[] args) { ThreadB b = new ThreadB(); b.start(); b.join(); // Wait for thread b to finish System.out.println("Total is: " + b.total); } } 

您还应该让ThreadB只实现Runnable而不是扩展Thread

 class ThreadB implements Runnable { int total; public void run() { for (int i = 0; i < 100; i++) { total += i; } } } 

然后使用它

 ThreadB tb = new ThreadB(); Thread b = new Thread(tb); 

您问题的众多可能解决方案之一是:

 public class ThreadA { public static final CyclicBarrier barrier = new CyclicBarrier(2); public static void main(String[] args) { ThreadB b = new ThreadB(); b.start(); try { barrier.await(); System.out.println("Total is: " + b.total); } catch (InterruptedException | BrokenBarrierException ex) { } } } class ThreadB extends Thread { int total; @Override public void run() { for (int i = 0; i < 100; i++) { total += i; } try { ThreadA.barrier.await(); } catch (InterruptedException | BrokenBarrierException ex) { } } }