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

Jar*_*zek 6 java multithreading

我写了一个永远不会停止的测试应用程序.它发布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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我正在测试Windows XP,Java 6.

Jon*_*eet 10

您正在等待Thread- 虽然大多数对象未被隐式通知,但Thread在线程终止时会通知对象.它记录的地方(我在寻找它...),你应该使用wait/ notifyThread对象,做为所内部完成.

这是为什么使用"私有"对象进行同步(以及等待/通知)的最佳实践的一个很好的例子 - 只有你的代码知道的东西.我经常使用类似的东西:

private final Object lock = new Object();
Run Code Online (Sandbox Code Playgroud)

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

  • @Jon, [Malcolm](http://stackoverflow.com/users/45668/malcolm) [发现](http://stackoverflow.com/a/16955524/772981) 在 [Java 7 Thread.join 文档]( http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join%28long%29)。 (2认同)

Phi*_*ler 8

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

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

  • @Boris如果发生虚假的唤醒,也不例外.只有在线程被中断时才会抛出`InterruptedException`. (3认同)
  • 我怀疑这实际上是*一个虚假的唤醒 - 我相信这是特别等待'线程'的行为; 它会在线程终止时得到通知.它在正常意义上并非虚假. (2认同)
  • 即使没有虚假的唤醒,使用监视器模式(或其任何变体),您总是希望循环并检查条件.如果稍后添加另一个条件,则可以防止出现问题(java和C#监视器使用一个对象作为锁和条件变量,因此每个条件不能使用一个条件变量).如果满足条件,它还会阻止您进行处理,但是等待同一对象的另一个线程首先出现,现在条件不再成立. (2认同)