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

时间:2016-04-21 16:42:12

标签: java multithreading java-8 runnable

我想同时运行一些任务,所以我有一个看起来像这样的代码:

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

我怎么知道所有任务何时完成(任务量可能不同),以便我可以在完成所有任务后运行某些任务?

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

6 个答案:

答案 0 :(得分:5)

不是显式创建线程,而是将Runnables提交给ExecutorService,然后调用其shutdownawaitTermination方法:

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

答案 1 :(得分:5)

较短的版本是使用parallelStream

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

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

答案 2 :(得分:1)

您还可以使用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处创建的线程将等到锁存器已经倒计数到零。只有这样,&#34;所有任务完成&#34;声明将被打印。所以基本上,doneSignal.await()之后的语句只会在所有线程完成后执行。

答案 3 :(得分:1)

答案 4 :(得分:0)

创建时,只需将每个帖子添加到列表中:

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

有关检查线程是否已完成的详细信息,请参阅此链接:

How to know if other threads have finished?

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

答案 5 :(得分:0)

另一种方法是使用Future interface。这样做可以为您提供一些其他漂亮的功能。有关示例,请参阅this