[英]Wait for all tasks in ExecutorService.execute to complete
How to wait for all tasks to be completed when they are submitted using使用提交时如何等待所有任务完成
ExecutorService.execute() . ExecutorService.execute() 。 There is a function called awaitTermination
有一个名为 awaitTermination 的function
But a timeout has to be provided in it.但是必须在其中提供超时。 Which is not a guarantee that when this
这不能保证当这
returns all the tasks would have been finished.返回所有任务将已完成。 Is there a way to achieve this?
有没有办法做到这一点?
If you read the javadoc of the ExecutorService.awaitTermination
(or look at the method signature) you will see it returns a boolean
.如果您阅读
ExecutorService.awaitTermination
的 javadoc(或查看方法签名),您将看到它返回boolean
。 This boolean indicates if the Executor
terminated or not.这个 boolean 指示
Executor
是否终止。 You can use that information to create a while
loop to determine if it has been terminated or not.您可以使用该信息创建一个
while
循环以确定它是否已终止。
ExecutorService executor = ...
executor.shutdown(); // close the executor and don't accept new tasks
while (!executor.awaitTermination(100, TimeUnit.MILLISECONDS) {}
Something like this will stop the executor and wait until it terminated and all tasks have finished.像这样的东西会停止执行器并等到它终止并且所有任务都完成。
execute method does not return anything.执行方法不返回任何东西。 You can use the submit method which returns a result of type Future.
您可以使用返回 Future 类型结果的submit方法。
Future<String> future =
executorService.submit(callableTask/runnableTask);
If you use class ThreadPoolExecutor or any of its children you have a method there getActiveCount() that returns the number of threads that are actively executing tasks.如果您使用 class ThreadPoolExecutor或其任何子项,则您有一个getActiveCount()方法,该方法返回正在执行任务的线程数。 So you can poll that method until it gets to 0, which would mean that all tasks have been completed and no new tasks are currently executing.
因此,您可以轮询该方法,直到它变为 0,这意味着所有任务都已完成并且当前没有新任务正在执行。 However, what if some task gets stuck?
但是,如果某些任务卡住了怎么办? I think you will have to also give some timeout in order to prevent infinite loop in this case.
我认为您还必须给出一些超时时间,以防止在这种情况下出现无限循环。
The biggest advantage of this idea is that you are not required to invoke shutdown method这个想法的最大优点是您不需要调用关闭方法
There are several approaches.有几种方法。
You can call first ExecutorService.shutdown and then ExecutorService.awaitTermination which returns:您可以先调用ExecutorService.shutdown ,然后调用ExecutorService.awaitTermination ,它会返回:
true if this executor terminated and false if the timeout elapsed before termination
如果此执行程序终止,则为 true;如果在终止前超时,则为 false
So:所以:
There is a function called awaitTermination But a timeout has to be provided in it.
有一个名为 awaitTermination 的 function 但必须在其中提供超时。 Which is not a guarantee that when this returns all the tasks would have been finished.
这并不能保证当它返回时所有任务都会完成。 Is there a way to achieve this?
有没有办法做到这一点?
You just have to call awaitTermination
in a loop.您只需要循环调用
awaitTermination
。
Using awaitTermination使用 awaitTermination
A full example with this implementation:此实现的完整示例:
public class WaitForAllToEnd {
public static void main(String[] args) throws InterruptedException {
final int total_threads = 4;
ExecutorService executor = Executors.newFixedThreadPool(total_threads);
for(int i = 0; i < total_threads; i++){
executor.execute(parallelWork(100 + i * 100));
}
int count = 0;
// This is the relevant part
// Chose the delay most appropriate for your use case
executor.shutdown();
while (!executor.awaitTermination(100, TimeUnit.MILLISECONDS)) {
System.out.println("Waiting "+ count);
count++;
}
}
private static Runnable parallelWork(long sleepMillis) {
return () -> {
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
// Do Something
}
System.out.println("I am Thread : " + Thread.currentThread().getId());
};
}
}
Using CountDownLatch使用 CountDownLatch
Another option is to create a CountDownLatch with a count
equals to the number of parallel tasks.另一种选择是创建一个
count
等于并行任务数的CountDownLatch 。 Each thread calls countDownLatch.countDown();
每个线程调用
countDownLatch.countDown();
, while the main thread calls countDownLatch.await();
, 而主线程调用
countDownLatch.await();
. .
A full example with this implementation:此实现的完整示例:
public class WaitForAllToEnd {
public static void main(String[] args) throws InterruptedException {
final int total_threads = 4;
CountDownLatch countDownLatch = new CountDownLatch(total_threads);
ExecutorService executor = Executors.newFixedThreadPool(total_threads);
for(int i = 0; i < total_threads; i++){
executor.execute(parallelWork(100 + i * 100, countDownLatch));
}
countDownLatch.await();
System.out.println("Exit");
executor.shutdown();
}
private static Runnable parallelWork(long sleepMillis, CountDownLatch countDownLatch) {
return () -> {
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
// Do Something
}
System.out.println("I am Thread : " + Thread.currentThread().getId());
countDownLatch.countDown();
};
}
}
Using Cyclic Barrier使用循环障碍
Another approach is to use a Cyclic Barrier另一种方法是使用循环障碍
public class WaitForAllToEnd {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
final int total_threads = 4;
CyclicBarrier barrier = new CyclicBarrier(total_threads+ 1);
ExecutorService executor = Executors.newFixedThreadPool(total_threads);
for(int i = 0; i < total_threads; i++){
executor.execute(parallelWork(100 + i * 100, barrier));
}
barrier.await();
System.out.println("Exit");
executor.shutdown();
}
private static Runnable parallelWork(long sleepMillis, CyclicBarrier barrier) {
return () -> {
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
// Do Something
}
System.out.println("I am Thread : " + Thread.currentThread().getId());
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
// Do something
}
};
}
}
There are other approaches but those would require changes to your initial requirements, namely:还有其他方法,但这些方法需要更改您的初始要求,即:
How to wait for all tasks to be completed when they are submitted using ExecutorService.execute().
使用 ExecutorService.execute() 提交所有任务时如何等待它们完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.