如何在 Java 中的每个线程完成运行后运行任务?

时间:2021-01-23 13:44:17

标签: java multithreading runnable

我有一个循环,每次迭代都会创建一个新线程,如下所示:

for(int i = 0; i < REPEAT; i++) {
    new Thread(new MyTask(i)).start();
    Thread.sleep(1);
}

private void finalTask() {
    //Some code to be executed once every threads stopped running
}

其中 MyTask 是一个实现 Runnable 的类。我的目标是:我想在每个线程停止后运行 finalTask​​。为了实现这一点,我尝试在每次线程完成运行时将变量加 1,一旦该变量等于 REPEAT,最终任务就会运行。但这没有用。我在 Google 和 StackOverlow 上搜索过我的问题的答案,但是关于这方面的信息很少,而且没有一个能正常工作。在最终任务之后总会有一个线程在运行。那我该怎么做?

3 个答案:

答案 0 :(得分:2)

您可以为此使用 CountDownLatch。 CountDownLatch 是

<块引用>

一种同步辅助,允许一个或多个线程等待其他线程中正在执行的一组操作完成。

CountDownLatch countDownLatch = new CountDownLatch(REPEAT);
for (int i = 0; i < REPEAT; i++) {
    new Thread(new MyTask(i, countDownLatch)).start();
    Thread.sleep(1);
}
finalTask(countDownLatch);

我创建了一个 CountDownLatch,其 count 被初始化为 REPEAT 的值。我将它传递给每个线程和 finalTask 方法。

每个线程在完成其工作后应调用 countDownLatch 的 countDown 方法。

private static class MyTask implements Runnable {

    private int i;
    private CountDownLatch countDownLatch;

    private MyTask(int i, CountDownLatch countDownLatch) {
        this.i = i;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        //Perform some task
        System.out.println("Running " + i);
        countDownLatch.countDown();
    }
}

finalTask 方法的第一行应该调用 CountDownLatch 的 await 方法。这将导致运行 finalTask 的线程等待,直到 CountDownLatch 的计数达到 0,即,直到所有线程(它们的重复数量)完成并调用 CountDownLatch 的 countDown

 private static void finalTask(CountDownLatch countDownLatch) {
    try {
        countDownLatch.await(); //this will wait until the count becomes 0.
    } catch (InterruptedException e) {
        e.printStackTrace(); //handle it appropriately
    }
    //Some code to be executed once all threads stopped running
    System.out.println("All done");
}

答案 1 :(得分:1)

另一种简单的方法是在所有线程上调用 join(),然后调用 finalTask()

Thread tasks[] = new Thread[REPEAT];

for(int i = 0; i < REPEAT; i++) {
    tasks[i] = new Thread(new MyTask(i));
    tasks[i].start();
}

for (Thread task : tasks) {
    for (;;) {
        try {
            task.join();
            break;
        }
        catch ( InterruptedException e ) {
            // catch code here
        }
    }
}

finalTask();

请注意,用于处理 InterruptedException 方法调用中可能出现的 join() 的代码几乎多于用于实现其余处理的代码。

答案 2 :(得分:0)

您可以将它们放入 CompletableFuture 中,然后使用 whenComplete()

CompletableFuture[] all =
IntStream.range(0, REPEAT+1).
  .mapToObj(i -> CompletableFuture.supplyAsync(new MyTask(i)))
  .toArray(CompletableFuture[]::new) ;
CompletableFuture.allOf(all).whenComplete((r, t) -> {
   // your code here
}) ;
相关问题