简体   繁体   English

等待 ExecutorService.execute 中的所有任务完成

[英]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.

相关问题 ExecutorService等待所有Future完成 - ExecutorService wait for all Future to complete 我是否需要同步ExecutorService.execute()? - Do I need to synchronize ExecutorService.execute()? ExecutorService.execute()不返回线程类型 - ExecutorService.execute() does not return the thread type ExecutorService,如何等待所有任务完成 - ExecutorService, how to wait for all tasks to finish 多个 ExecutorService.execute() 调用。 线程池。 冗余? - multiple ExecutorService.execute() calls. Threadpool. Redundancy? android:ExecutorService:-ExecutorService不等待executorService完成 - android:ExecutorService:- ExecutorService does not wait for executorService to complete ExecutorService-如何以非阻塞方式等待所有任务的完成 - ExecutorService - How to wait for completition of all tasks in non-blocking style Java 中这段代码中的 ExecutorService.submit 和 ExecutorService.execute 有什么区别? - What is the difference between ExecutorService.submit and ExecutorService.execute in this code in Java? 如何等待直到ExecutorService中的所有提交任务都完成而没有关闭? - How to wait until all submitted tasks in ExecutorService are completed without shutdown? Executorservice 等待任务完成后 - Executorservice wait after tasks are finished
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM