在 Java 中等待多个线程完成

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1361029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 11:09:59  来源:igfitidea点击:

Waiting on multiple threads to complete in Java

javamultithreadingsynchronization

提问by A Hymanson

During the course of my program execution, a number of threads are started. The amount of threads varies depending on user defined settings, but they are all executing the same method with different variables.

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

In some situations, a clean up is required mid execution, part of this is stopping all the threads, I don't want them to stop immediately though, I just set a variable that they check for that terminates them. The problem is that it can be up to 1/2 second before the thread stops. However, I need to be sure that all threads have stopped before the clean up can continues. The cleanup is executed from another thread so technically I need this thread to wait for the other threads to finish.

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

I have thought of several ways of doing this, but they all seem to be overly complex. I was hoping there would be some method that can wait for a group of threads to complete. Does anything like this exist?

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

Thanks.

谢谢。

采纳答案by Jon Skeet

Just join them one by one:

只需一一加入:

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

(You'll need to do something with InterruptedException, and you may well want to provide a time-out in case things go wrong, but that's the basic idea...)

(您需要对 做一些事情InterruptedException,并且您可能希望提供超时以防出现问题,但这是基本思想......)

回答by oxbow_lakes

Define a utility method (or methods) yourself:

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

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

Or you may have an array

或者你可能有一个数组

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

Alternatively you could look at using a CyclicBarrierin the java.util.concurrentlibrary to implement an arbitrary rendezvouspoint between multiple threads.

另外,您可以看看使用CyclicBarrierjava.util.concurrent库来实现任意交会多个线程之间的点。

回答by Tadeusz Kopec

If you are using java 1.5 or higher, you can try CyclicBarrier. You can pass the cleanup operation as its constructor parameter, and just call barrier.await()on all threads when there is a need for cleanup.

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

回答by Kenster

Have you seen the Executorclasses in java.util.concurrent? You could run your threads through an ExecutorService. It gives you a single object you can use to cancel the threads or wait for them to complete.

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

回答by rogerdpack

If you control the creation of the Threads (submission to an ExecutorService) then it appears you can use an ExecutorCompletionServicesee ExecutorCompletionService? Why do need one if we have invokeAll?for various answers there.

如果您控制线程的创建(提交给 ExecutorService),那么您似乎可以使用ExecutorCompletionService查看ExecutorCompletionService?如果我们有 invokeAll 为什么需要一个?那里的各种答案。

If you don't control thread creation, here is an approach that allows you to join the threads "one by one as they finish" (and know which one finishes first, etc.), inspired by the ruby ThreadWaitclass. Basically by newing up "watching threads" which alert when the other threads terminate, you can know when the "next" thread out of many terminates.

如果您不控制线程创建,这里有一种方法允许您“在线程完成时一个一个地”加入线程(并知道哪个线程先完成等等),其灵感来自 ruby ThreadWait类。基本上,通过更新在其他线程终止时发出警报的“观察线程”,您可以知道许多线程中的“下一个”线程何时终止。

You'd use it something like this:

你会像这样使用它:

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

And the source:

和来源:

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

The nice part of this is that it works with generic Java threads, without modification, any thread can be joined. The caveat is it requires some extra thread creation. Also this particular implementation "leaves threads behind" if you don't call joinNextThread() the full number of times, and doesn't have an "close" method, etc. Comment here if you'd like a more polished version created. You could also use this same type of pattern with "Futures" instead of Thread objects, etc.

这样做的好处是它可以与通用 Java 线程一起使用,无需修改,任何线程都可以加入。需要注意的是,它需要一些额外的线程创建。如果您没有完整地调用 joinNextThread() 并且没有“关闭”方法等,这个特定的实现也会“留下线程”。如果您想要创建更精美的版本,请在此处发表评论。您也可以将这种相同类型的模式与“期货”而不是线程对象等一起使用。