Java是否隐式通知等待线程? [英] Does Java notify waiting threads implicitly?
问题描述
我写了一个应该永远不会停止的测试应用。它发出 t.wait()
( t
是一个线程
对象),但我从不打电话通知。为什么这段代码会结束?
尽管主线程在 t
上同步,但生成的线程会运行,因此它不会锁定此对象。
I wrote a test app that should never stop. It issues t.wait()
(t
is a Thread
object), but I never call notify. Why does this code end?
Despite the main thread synchronizing on t
, the spawned thread runs, so it doesn't lock this object.
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()
不等待。如果主线程不会休眠5秒(注释这一行),那么 t.wait()
实际上会等到工作人员完成。当然, join()
是一种在这里使用的方法,但是,出乎意料的是, wait()
做同样的事情as join()
。为什么?
The result is that the main thread waits 5 seconds and during this time worker gives its output. Then after 5 seconds are finished, the program exits. t.wait()
does not wait. If the main thread wouldn't sleep for 5 seconds (commenting this line), then t.wait()
would actually wait until the worker finishes. Of course, join()
is a method to use here, but, unexpectedly, wait()
does the same thing as join()
. Why?
也许JVM看到了,因为只有一个线程正在运行,所以没有机会通知主线程并解决死锁问题。如果这是真的,它是一个记录的功能吗?
Maybe the JVM sees that, since only one thread is running, there is no chance to notify the main thread and solves the deadlock. If this is true, is it a documented feature?
我在Windows XP,Java 6上进行测试。
I'm testing on Windows XP, Java 6.
推荐答案
您正在等待线程
- 并且大多数对象未被隐式通知,线程终止时通知线程
对象。它记录在某处(我正在寻找它......)你不使用等待
/ 通知
on Thread
对象,就像在内部完成的那样。
You're waiting on a Thread
- and while most objects aren't implicitly notified, a Thread
object is notified when the thread terminates. It's documented somewhere (I'm looking for it...) that you should not use wait
/notify
on Thread
objects, as that's done internally.
这是一个很好的例子,为什么它是使用私有对象进行同步(以及等待/通知)的最佳做法 - 您的代码只知道 的内容。我通常使用类似的东西:
This is a good example of why it's best practice to use a "private" object for synchronization (and wait/notify) - something which only your code knows about. I usually use something like:
private final Object lock = new Object();
(但是,一般来说,使用java提供的一些更高级别的抽象更清晰。 util.concurrent如果可以的话。如评论中所述,实现 Runnable
而不是扩展 Thread
也是一个好主意。你自己。)
(In general, however, it's cleaner to use some of the higher-level abstractions provided by java.util.concurrent if you can. As noted in comments, it's also a good idea to implement Runnable
rather than extending Thread
yourself.)
这篇关于Java是否隐式通知等待线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!