我在java中有一组线程,我想运行几次(每次使用一组不同的参数)。为了开始第二次运行,我想等待第一次运行完成。这应该可以在第二次运行之前使用 Thread.join() 轻松完成,但由于我的线程在无限循环中运行,我必须通过中断来停止它们,这也会中断阻塞连接:
我有一个线程,其 run()
方法基本上如下所示:
try {
while(true) {
printSomeInfo();
if (...) {
Thread.currentThread().getThreadGroup().interrupt();
}
}
} catch (InterruptedException e) {
Thread.currentThread().getThreadGroup().interrupt();
} finally {
printStats();
}
还有一个调用线程run方法的main方法:
System.out.println("New run:");
for (i ...) { //first run
myThread[i] = new MyThread(someInfoString1);
myThread[i].start();
}
try {
for (i...) {
myThread[i].join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("New run:");
for (i ...) { //second run
myThread[i] = new MyThread(someInfoString2);
myThread[i].start();
}
try {
for (i...) {
myThread[i].join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
我的问题是第二次运行开始打印信息,而第一次运行则没有使用finally block 中的 printStats() 方法完成打印。 所以输出看起来像这样:
New run:
Info 1
Info 1
...
Info 1
New run:
(here comes the stack trace)
Info 2
Info 2
Stats 1 <- this should happen before the second "New run:"
...
Info 2
Stats 2
我怎样才能真正等待第一组线程完成?是否有一种更有选择性的方法来中断正在运行的线程?
最佳答案
问题在于您重复使用Thread.currentThread().getThreadGroup().interrupt()
它会中断 ThreadGroup
中的所有线程,包括名为 join
的那个.
如果你看看你的循环,你就会发现 InterruptedException
,但无法正确恢复。您的循环包含在 try…catch
中 block 并因此被异常强制终止。既然你要调用join
在所有线程上,您必须继续循环,包括 join
已中断的通话:
threads: for (i...) { // loop over all threads
for(;;) { // recover join on InterruptedException
try {
myThread[i].join();
continue threads; // after successful join
} catch (InterruptedException e) {} // call join again
}
}
通常,中断整个 ThreadGroup
,或者根本处理过时的线程组概念,都不是正确的软件设计。您应该重写您的软件以仅中断预期的线程。或者简单地使用并发框架,尤其是。 ExecutorService
它已经提供了提交任务组并取消或等待所有任务的方法。
关于java - 如何在 java 中等待一组线程 'really' 完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27245731/