我有 n 个线程并行运行,每个线程都执行一些自定义逻辑。但是,我的要求是,当任何线程完成执行时,所有其他线程都应该停止执行并返回。
实现这一点的最佳方法是什么?我想通过共享布尔变量来做到这一点。当任何线程完成执行时,它将设置布尔值。所有所有线程都会定期读取此变量并在设置时退出。
此外,我的自定义逻辑是一个无限循环,一旦我知道其他线程已完成执行,我想在当前迭代后停止执行。
这样做的正确方法是什么?
我有 n 个线程并行运行,每个线程都执行一些自定义逻辑。但是,我的要求是,当任何线程完成执行时,所有其他线程都应该停止执行并返回。
实现这一点的最佳方法是什么?我想通过共享布尔变量来做到这一点。当任何线程完成执行时,它将设置布尔值。所有所有线程都会定期读取此变量并在设置时退出。
此外,我的自定义逻辑是一个无限循环,一旦我知道其他线程已完成执行,我想在当前迭代后停止执行。
这样做的正确方法是什么?
使用 anExecutorService
及其.invokeAny()
方法(注意:还有一个带有超时的版本)。
来自 Javadoc:
执行给定任务,返回已成功完成的任务的结果(即,不抛出异常),如果有的话。
你有你的结果,.shutdown()
执行者。
查看Executors
课程以获得适合您需求的执行器。
另一个解决方案是ExecutorCompletionService
类;在这种情况下,您将.take()
代替.invokeAny()
, 并且必须一一提交每个任务。而且您还必须保留对您的引用,ExecutorService
因为您需要一个作为参数,并且还需要将其关闭。
(注意:如果您不返回结果,请创建实例)Callable<
Void
>
我更喜欢使用通用信号量来控制执行,并经常检查线程。
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
变量。静态是因为所有线程都必须访问同一个标志,易失是为了防止 JVM 缓存其数据。如果您不将其标记为易失性,编译器可能会生成这样的字节码,它会优化从字段中读取的方式,使其仅读取该字段一次,并在每次循环执行时使用保存的值。
如果您的任务不同并且您实现了不同的循环,则可以使用任何外部public static volatile boolean
字段来保存标志。
该解决方案不依赖于线程的等待状态。您可以检查isDone
循环中的多个位置(甚至在每个代码块之前)。如果您保证您的代码将达到退出检查,则无论如何都无需中断线程。
看,您可以将所有 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 以来已经有一段时间了,这个想法是你明白了;)