我遇到的问题是,在我打电话给wait()
之前,有时候我开始使用的话题已经完成。这似乎导致我的程序等待不会再发生的事情(notify()
)。我怎样才能确保不要等待完成的线程?
void someFunction() {
MyThread thread = new MyThread();
thread.start();
// .. some stuff that takes sometimes quite long
synchronized(thread) {
try {
thread.wait();
} catch(InterruptedException e) {
// ..
}
}
}
答案 0 :(得分:2)
如果您阅读了线程的JavaDocs,它会告诉您永远不会在Thread对象上使用wait, notify, or notifyAll
。你应该使用join()
答案 1 :(得分:1)
您可以使用:
而不是wait()thread.join()
但我不知道你情况的背景。
答案 2 :(得分:1)
您正在查看"丢失的通知"问题。 (即,你没有以正确的方式使用wait()。)
当您致电foo.wait()
时,总是等待您可以明确测试的某些条件。例如,像这样:
boolean condition;
synchronized(foo) {
while (! condition) {
foo.wait();
}
doSomethingThatRequiresConditionToBeTrue();
}
当你做任何使条件成立的事情时,它应该是这样的:
synchronized(foo) {
doSomethingThatMakesConditionTrue();
foo.notify();
}
如果你做任何使条件失败的事情,它应该是这样的:
synchronized(foo) {
doSomethingThatMakesConditionFalse();
}
请注意:
任何触及condition
的代码都会被同步,并且始终在同一个对象上同步。
当条件为真时,foo.wait()
无法被调用。
循环调用wait()
。
Point(2)是至关重要的,因为如果没有其他线程等待通知,foo.notify()
根本不做任何事情。任何人都在等待的通知是#34;丢失"。 foo
对象不记得已通知。
第(3)点很重要,原因有两个。主要的是,如果线程A调用foo.wait(),然后线程B使条件为true并调用foo.notify();当wait()调用最终在线程A中返回时,不能保证条件仍然为真。其他一些线程可能使条件再次为假。在许多应用程序中,这是一个非常真实的场景。
第(3)点重要的另一个原因是,即使没有调用foo.notify(),Java语言规范也允许foo.wait()返回。这被称为“虚假唤醒”,并允许它发生,这使得在某些操作系统上实现JVM变得更加容易。
答案 3 :(得分:0)
调用线程上的等待有时会起作用,因为当一个线程终止时,它会向等待它的每个线程发送一个通知。但是如果线程在当前线程调用wait之前已经终止,则不会发生任何通知。
使用join的建议是正确的,James Large的答案是正确的,你的代码应该在一个带有条件变量的循环中等待。这正是join正在做的事情,如果你查看java.lang.Thread.join的代码(其中join不带参数默认为0,wait(0)表示等待没有超时):
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;
}
}
}
它有一个循环,它测试Thread的活动标志,如果是真,那么它继续等待。如果线程已经终止,那么线程将不会等待,因此当前线程在完成连接线程之后等待的情况不会发生。