繁体   English   中英

在 Java 中等待多个线程完成

[英]Waiting on multiple threads to complete in Java

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

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

我已经想到了几种方法来做到这一点,但它们似乎都过于复杂。 我希望有一些方法可以等待一组线程完成。 这样的事情存在吗?

只需逐个加入:

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

(你需要用InterruptedException做一些事情,你可能希望在出现问题时提供超时,但那是基本的想法...)

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

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

自己定义一种实用方法(或多种方法):

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));
}

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

如果你控制Threads的创建(提交给ExecutorService),那么看来你可以使用ExecutorCompletionServiceExecutorCompletionService吗? 如果我们有invokeAll,为什么需要一个? 在那里有各种答案。

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

你会用这样的东西:

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对象等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM