为什么没有线程等待notify()?

为什么没有线程等待notify() ? 线程启动然后进入等待池,但是在那之后它继续执行。

 public class JavaApplication2 { public static void main(String [] args) { ThreadB b = new ThreadB(); synchronized(b) { b.start(); try { System.out.println("1"); b.wait(); } catch (InterruptedException e) {} System.out.println("Total is: " + b.total); } } } class ThreadB extends Thread { int total; @Override public void run() { synchronized(this) { total += 1; //notify(); } } } 

您正在同步线程对象本身,这是错误的用法。 发生的事情是,垂死的执行线程总是在其Thread对象上调用notifyThread.join 依赖于此 。 因此很清楚为什么在那里使用和不使用自己的notify会得到相同的行为。

解决方案:使用单独的对象进行线程协调; 这是标准做法。

为终止线程的Thread对象调用方法notifyAll() 。 这个事实在Thread.join的描述中有奇怪的记录,使用以下句子:

当一个线程终止时,将调用this.notifyAll方法。 建议应用程序不要在Thread实例上使用wait,notify或notifyAll。

因此,如果您没有明确阅读您不一定需要的join描述,则无法了解奇怪行为的原因。

你不能依赖于等待直到通知:“中断和虚假唤醒是可能的”。 通常,您应该在循环中包含等待调用,而线程应该继续等待。

如果您尝试在ThreadB任何对象上同步代码,您将发现它永远不会终止。 这是因为有一个隐藏的notify

虽然我不知道任何指定的内容,但Thread会在结束时通知自己。 这是实现join方法的隐含方式。 这是join的代码:

 public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } } 

(来自JDK7源代码)

正如您所看到的,只有在线程结束后调用notify某个地方,才会发出wait调用。 同一个notify调用是允许程序终止的。

您在两个位置嵌套了synchronized {}构造。 这些构造似乎做了一些奇怪的事情:线程根本没有对notify进行反应,只在ThreadB(b)终止时才恢复。 删除这个:

 public class JavaApplication2 { public static void main(String[] args) { ThreadB b = new ThreadB(); b.start(); try { System.out.println(" ### Waiting for notify"); synchronized (b) { b.wait(); } System.out.println(" ### Notified"); } catch (InterruptedException e) { } System.out.println("### Total is: " + b.total); } } class ThreadB extends Thread { int total; @Override public void run() { total += 1; System.out.println(" *** Ready to notify in 5 secs"); try { Thread.sleep(5000); } catch (InterruptedException e) { } System.out.println(" *** Notification sent"); synchronized (this) { notify(); } System.out.println(" *** 5 sec post notification"); try { Thread.sleep(5000); } catch (InterruptedException e) { } System.out.println(" *** ThreadB exits"); } } 

上面的代码可能正常工作:使用notify(),主线程在5秒后恢复,然后我们看到ThreadB终止的消息。 随着notify()被注释掉,主线程在10秒之后和关于ThreadB终止的消息之后恢复,因为notify()从其他代码调用anywhay。 Marko Topolnik解释了为什么以及这个“幕后”notify()调用的来源。

我正在读取OCP SE 7时对wait / notify操作进行相同的测试,这很好。 我想我们应该让authoer解释一下。