我有n个并行运行的线程,每个线程都有一些自定义逻辑。但是,我的要求是当任何线程完成执行时,所有其他线程应该停止执行并返回。
实现此目的的最佳方法是什么?我想通过拥有一个共享的布尔变量来做到这一点。当任何线程完成执行时,它将设置布尔值。所有线程都定期读取此变量,并在设置时退出。
另外,我的自定义逻辑是一个无限循环,一旦我知道其他一些线程已经完成执行,我想在当前迭代后停止执行。
这样做的正确方法是什么?
答案 0 :(得分:8)
使用ExecutorService
及其.invokeAny()
方法(注意:还有一个超时的版本)。
来自Javadoc:
执行给定的任务,返回已成功完成的任务的结果(即,不抛出异常),如果有的话。
你有一个结果,.shutdown()
执行者。
请参阅Executors
class以获得符合您需求的执行人。
另一个解决方案是ExecutorCompletionService
类;在这种情况下,您需要.take()
而不是.invokeAny()
,并且必须逐个提交每项任务。而且你还必须保留对ExecutorService
的引用,因为你需要一个作为参数,并且还需要关闭它。
(注意:如果您未返回结果,请制作Callable<
Void
>
个实例)
答案 1 :(得分:0)
我更喜欢使用通用信号量来控制执行,并经常检查线程。
public class MyTask implements Runnable {
private static volatile boolean isDone = false
@Override
public void run() {
while(true) {
if (isDone) {
break;
}
// do some calculation, no wait() s
if (...has result...) {
isDone = true;
break;
}
}
}
}
Thread t1 = new Thread(new MyTask());
Thread t2 = new Thread(new MyTask());
Thread t3 = new Thread(new MyTask());
t1.start();
t2.start();
t3.start();
您必须注意的唯一事情是static volatile boolean
变量。 静态,因为所有线程都必须访问相同的标志, volatile 以防止JVM缓存其数据。如果你没有将它标记为volatile,编译器可能会生成这样一个字节码,它会优先从字段中优化 read ,这样它只读取一次字段,并使用保存的值每个循环执行。
如果您的任务不同并且实现了不同的循环,则可以使用任何外部public static volatile boolean
字段来保存标记。
此解决方案不依赖在线程的 wait 状态。您可以在循环中检查isDone
多个位置(甚至在每个代码块之前)。如果您保证您的代码将进行退出检查,则无需中断线程。
答案 2 :(得分:0)
看,你可以在所有Thread对象上保持共享全局数组,然后在每个任务结束时,你可以执行一个“清理”函数的调用,该函数只接受所有这些对象并执行“中断”调用在他们。这将导致第一个线程完成其余部分的执行。
public class MyMain
{
public static Thread workers[NUM_WORK];
public static void main(..)
{
MyMain.workers[0] = new Thread(new MyTask0());
.
.
.
MyMain.workers[n] = new Thread(new MyTaskN());
//Then start them all..
// And wait for them unless you want them to die before execution ;)
}
}
然后是你的其他工人
import MyMain;
public class MyTaskI implements Runnable
{
public void run()
{
//Do all the work
for(Thread t : MyMain.workers)
{
// If it is not this thread
t.interrupt();
}
}
}
很抱歉,如果我发现任何语法错误。自从我做Java以来已经有一段时间了,我的想法是你明白了这一点;)