Java - 如何告诉所有子线程完成

Java - How to tell all subthreads are done

我想同时 运行 几个任务,所以我有一个如下所示的代码:

for(final Task task : tasks){
    (new Thread(){public void run(){
        task.run(args);
}}).start();

我如何知道所有任务何时完成(任务的数量可能会有所不同)以便我可以 运行 只有在所有任务都完成后才能做一些事情?

System.out.println("All tasks are finished");

创建线程时只需将每个线程添加到列表中即可:

LinkedList<Thread> threads = new LinkedList<>();

当你创建一个新线程时:

Thread t = new Thread() {
    public void run() {
        task.run(args);
    }
}
threads.add(t);

然后您可以检查您列表中的每个线程,看它是否已完成:

boolean allFinished = true;

for (Thread t : threads) {
 if (t.isAlive()) {
  allFinished = false;
  break;
 }
}

有关检查线程是否已完成的更多信息,请参阅此 link:

How to know if other threads have finished?

这个问题的关键点是,如果你想稍后检查线程,你必须在某处存储它们的列表(或数组等)。

不要显式创建线程,而是将您的 Runnable 提交给 ExecutorService,然后调用它的 shutdown and awaitTermination 方法:

ExecutorService executor = Executors.newFixedThreadPool(tasks.size());

for (final Task task : tasks) {
    executor.submit(new Runnable() {
        @Override
        public void run() {
            task.run(args);
        }
    });
}

executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLSECONDS);

另一种方法是使用 Future interface. Doing it this way gives you some other nifty features. See this 来举例。

您还可以使用 CountDownLatch 来指示线程是否完成。参见 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html

像这样:

public static class Task {
    void run(String args[]) {
        System.out.println("Hello");
    }
}

public static void main(String[] args) {
    List<Task> tasks = Arrays.asList(new Task(), new Task(), new Task());
    CountDownLatch doneSignal = new CountDownLatch(tasks.size());

    for(final Task task : tasks) {
        (new Thread() {
            public void run(){
                task.run(args);
            }
        }).start();
        doneSignal.countDown();  //counts latch down by one
    }

    //A
    new Thread() {
        public void run() {
            try {
                doneSignal.await(); //blocks until latch counted down to zero
                System.out.println("All tasks completed");
            } catch(Exception e) {
                System.out.println("Warning: Thread interrupted.");
            }
        }
    }.start();
}

每个任务线程在完成时都会对锁存器进行倒数计数。在//A 处创建的线程将等待直到锁存器倒计时为零。只有这样,才会打印 "All tasks completed" 语句。所以基本上 doneSignal.await() 之后的语句只会在所有线程完成后执行。

使用 CyclicBarrier ,例如: http://tutorials.jenkov.com/java-util-concurrent/cyclicbarrier.html

一个较短的版本是使用 parallelStream

tasks.parallelStream().forEach(t -> t.run(args));

这将 运行 所有任务,使用您拥有的所有 CPU(如果您有足够的任务)并等待全部完成。