java线程之间的通信:当一个线程完成其任务时停止所有线程

时间:2013-06-18 10:44:54

标签: java multithreading

我有n个并行运行的线程,每个线程都有一些自定义逻辑。但是,我的要求是当任何线程完成执行时,所有其他线程应该停止执行并返回。

实现此目的的最佳方法是什么?我想通过拥有一个共享的布尔变量来做到这一点。当任何线程完成执行时,它将设置布尔值。所有线程都定期读取此变量,并在设置时退出。

另外,我的自定义逻辑是一个无限循环,一旦我知道其他一些线程已经完成执行,我想在当前迭代后停止执行。

这样做的正确方法是什么?

3 个答案:

答案 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以来​​已经有一段时间了,我的想法是你明白了这一点;)