等待多个线程在Java中完成

时间:2009-09-01 07:28:45

标签: java multithreading synchronization

在程序执行过程中,会启动许多线程。线程数量取决于用户定义的设置,但它们都使用不同的变量执行相同的方法。

在某些情况下,执行过程中需要清理,其中一部分是停止所有线程,我不希望它们立即停止,我只是设置一个他们检查的变量来终止它们。问题是它可以在线程停止前最多1/2秒。但是,我需要确保在清理可以继续之前所有线程都已停止。清理是从另一个线程执行的,所以从技术上讲,我需要这个线程来等待其他线程完成。

我想过几种方法,但它们似乎都过于复杂。我希望有一些方法可以等待一组线程完成。有这样的事吗?

感谢。

5 个答案:

答案 0 :(得分:56)

只需逐个加入:

for (Thread thread : threads) {
  thread.join();
}

(您需要对InterruptedException执行某些操作,并且您可能希望在出现问题时提供超时,但这是基本想法......)

答案 1 :(得分:14)

如果您使用的是Java 1.5或更高版本,则可以尝试CyclicBarrier。您可以将清理操作作为其构造函数参数传递,并在需要清理时在所有线程上调用barrier.await()

答案 2 :(得分:8)

自己定义一种实用方法(

public static waitFor(Collection<? extends Thread) c) throws InterruptedException {
    for(Thread t : c) t.join();
}

或者你可能有一个数组

public static waitFor(Thread[] ts) throws InterruptedException {
    waitFor(Arrays.asList(ts));
}

或者,您可以使用CyclicBarrier库中的java.util.concurrent来实现多个线程之间的任意集合点。

答案 3 :(得分:7)

您是否在Executor中看到过java.util.concurrent个班级?您可以通过ExecutorService运行线程。它为您提供了一个可用于取消线程或等待它们完成的对象。

答案 4 :(得分:1)

如果你控制线程的创建(提交给ExecutorService),那么看起来你可以使用ExecutorCompletionService 请参阅ExecutorCompletionService? Why do need one if we have invokeAll?了解各种答案。

如果你不控制线程创建,这里有一种方法,允许你在“完成”时逐个加入线程(并知道哪一个完成,等等),受到红宝石的启发{{3 } .class。 基本上通过新建“监视线程”,当其他线程终止时,它会发出警报,你可以知道许多终止的“下一个”线程何时终止。

您可以使用以下内容:

JoinThreads join = new JoinThreads(threads);
for(int i = 0; i < threads.size(); i++) {
  Thread justJoined = join.joinNextThread();
  System.out.println("Done with a thread, just joined=" + justJoined);
}

来源:

public static class JoinThreads {
  java.util.concurrent.LinkedBlockingQueue<Thread> doneThreads = 
      new LinkedBlockingQueue<Thread>();

  public JoinThreads(List<Thread> threads) {
    for(Thread t : threads) {
      final Thread joinThis = t;
      new Thread(new Runnable() {
        @Override
        public void run() {
          try {
            joinThis.join();
            doneThreads.add(joinThis);
          }
          catch (InterruptedException e) {
            // "should" never get here, since we control this thread and don't call interrupt on it
          }
        }
      }).start();
    }

  }

  Thread joinNextThread() throws InterruptedException {
    return doneThreads.take();
  }
}

这很好的部分是它适用于通用Java线程,无需修改,任何线程都可以连接。需要注意的是,它需要一些额外的线程创建。如果你没有多次调用joinNextThread(),并且没有“关闭”方法等,这个特殊的实现“会留下线程”。如果你想要创建一个更精美的版本,请在此处注释。你也可以使用相同类型的模式和“Futures”而不是Thread对象等。

相关问题