我有一个循环,每次迭代都会创建一个新线程,如下所示:
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 上搜索过我的问题的答案,但是关于这方面的信息很少,而且没有一个能正常工作。在最终任务之后总会有一个线程在运行。那我该怎么做?
答案 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
}) ;