如何在 运行 每个线程在 Java 中完成 运行 后执行任务?
How to run a task once every Threads finished running in Java?
我有一个循环,它在每次迭代时创建一个新线程,如下所示:
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 是 class 实现 Runnable。我的目标是:一旦每个线程停止,我想 运行 finalTask。为实现这一点,我尝试在线程每次完成 运行ning 时将变量递增 1,并且一旦该变量等于 REPEAT,最终任务将 运行。但这没有用。我在 Google 和 StackOverlow 上搜索了我的问题的答案,但是关于这个的信息很少,而且 none 的信息也有效。在最终任务之后总会有一个线程 运行ning。那我该怎么做呢?
您可以为此使用 CountDownLatch
。 CountDownLatch 是
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
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");
}
您可以将它们放入 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
}) ;
另一种简单的方法是在所有线程上 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();
请注意,用于处理来自 join()
方法调用的可能 InterruptedException
的代码几乎多于用于实现其余处理的代码。
我有一个循环,它在每次迭代时创建一个新线程,如下所示:
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 是 class 实现 Runnable。我的目标是:一旦每个线程停止,我想 运行 finalTask。为实现这一点,我尝试在线程每次完成 运行ning 时将变量递增 1,并且一旦该变量等于 REPEAT,最终任务将 运行。但这没有用。我在 Google 和 StackOverlow 上搜索了我的问题的答案,但是关于这个的信息很少,而且 none 的信息也有效。在最终任务之后总会有一个线程 运行ning。那我该怎么做呢?
您可以为此使用 CountDownLatch
。 CountDownLatch 是
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
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");
}
您可以将它们放入 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
}) ;
另一种简单的方法是在所有线程上 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();
请注意,用于处理来自 join()
方法调用的可能 InterruptedException
的代码几乎多于用于实现其余处理的代码。