我正在尝试构造两个线程,线程A是主线程,线程B是第二个线程,线程B通过耗时的函数更新变量(这个变量应该在两个线程之间共享,因为最终线程A需要使用该变量),但是如果线程B花费太长时间来完成(使用异常),我希望线程A终止线程B.
我尝试的是以下内容:
Thread thread = new Thread() {
public void run() {
/// run something that could take a long time
}
};
synchronized (thread) {
thread.start();
}
System.err.println("Waiting for thread and terminating it if it did not stop.");
try {
thread.wait(10000);
} catch (InterruptedException e) {
System.err.println("interrupted.");
}
如果行为超过10秒,是否会产生终止行为的预期行为?在等待之后线程对象被删除,因为运行该线程的方法返回。
现在,这段代码发生的事情是我总是在wait(10000)命令上得到java.lang.IllegalMonitorStateException。
答案 0 :(得分:3)
如果您在IllegalMonitorStateException
上没有wait()
的对象上致电synchronized
,您将始终获得try {
// you need this to do the wait
synchronized (thread) {
thread.wait(10000);
}
} catch (InterruptedException e) {
System.err.println("interrupted.");
}
。
thread
如果您正在等待try {
thread.join(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("interrupted.");
}
完成,那么您可能正在尝试:
join
不幸的是,你不知道线程是否正在运行,因为thread.isAlive()
不会返回它是否超时(抱怨)。因此,您需要测试加入后是否thread
。
如果您问如何取消10000
如果其运行时间超过thread.interrupt()
毫秒,那么正确的做法就是使用sleep()
。这将导致任何wait()
或InterruptedException
方法抛出 while (!Thread.currentThread.isInterrupted()) {
// do it's thread stuff
}
,它将在线程上设置中断标志。
要使用中断标志,您的线程应该执行以下操作:
InterruptedException
此外,执行类似以下操作总是一个好的模式,因为一旦抛出} catch (InterruptedException e) {
// set the interrupt flag again because InterruptedException clears it
Thread.currentThread.interrupt();
System.err.println("interrupted.");
}
,中断标志就被清除了:
{{1}}
答案 1 :(得分:1)
该代码不正确。方法wait
在Object
类中声明,旨在使用作为调用它的对象的监视器实例来挂起当前线程。您可以仅在synchronized
部分调用此方法,这就是您获得异常的原因。
关于你的问题:一般来说,如果不想停止,你就无法阻止另一个线程。因此,您应该调用Thread.interrupt
来通知线程它应该停止工作,并由该线程决定是否考虑该通知。要检查线程是否被中断,您可以使用interrupted()
或isInterrupted()
方法。