Java是否隐式通知等待线程?

我写了一个永远不会停止的测试应用程序。 它发出t.wait()t是一个Thread对象),但我从不调用notify。 为什么这段代码会结束? 尽管主线程在t同步,但是生成的线程会运行,因此它不会锁定此对象。

 public class ThreadWait { public static void main(String sArgs[]) throws InterruptedException { System.out.println("hello"); Thread t = new MyThread(); synchronized (t) { t.start(); Thread.sleep(5000); t.wait(); java.lang.System.out.println("main done"); } } } class MyThread extends Thread { public void run() { for (int i = 1; i <= 5; i++) { java.lang.System.out.println("" + i); try { Thread.sleep(500); } catch (Exception e) { throw new RuntimeException(e); } } } } 

结果是主线程等待5秒,在此期间工作人员给出其输出。 然后在5秒钟结束后,程序退出。 t.wait()不等待。 如果主线程不会hibernate5秒(注释这一行),那么t.wait()实际上会等到工作完成。 当然, join()是一种在这里使用的方法,但是,出乎意料的是, wait()join()做同样的事情。 为什么?

也许JVM看到了,因为只有一个线程正在运行,所以没有机会通知主线程并解决死锁问题。 如果这是真的,它是一个记录的function吗?

我正在测试Windows XP,Java 6。

您正在等待Thread – 虽然大多数对象未被隐式通知,但线程终止时会通知Thread对象。 它记录在某处(我正在寻找它……)你不应该在Thread对象上使用wait / notify ,因为这是在内部完成的。

这是一个很好的例子,说明为什么最好的做法是使用“私有”对象进行同步(以及等待/通知) – 只有你的代码知道的东西。 我通常使用类似的东西:

 private final Object lock = new Object(); 

(一般情况下,如果可以的话,使用java.util.concurrent提供的一些更高级别的抽象会更清晰。如注释中所述,实现Runnable而不是自己扩展Thread也是一个好主意。)

JavaDoc for wait给出了答案:虚假唤醒是可能的。 这意味着JVM可以随时结束调用以wait它。

如果您不想要这个(可能总是这样),文档甚至会为您提供解决方案:将调用wait循环并检查您等待的条件是否在每次唤醒后变为真。