How to wait for all threads to finish, using ExecutorService?

前端 未结 26 1999
你的背包
你的背包 2020-11-22 01:55

I need to execute some amount of tasks 4 at a time, something like this:

ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
    tas         


        
相关标签:
26条回答
  • 2020-11-22 02:33

    You could use your own subclass of ExecutorCompletionService to wrap taskExecutor, and your own implementation of BlockingQueue to get informed when each task completes and perform whatever callback or other action you desire when the number of completed tasks reaches your desired goal.

    0 讨论(0)
  • 2020-11-22 02:33

    You could call waitTillDone() on this Runner class:

    Runner runner = Runner.runner(4); // create pool with 4 threads in thread pool
    
    while(...) {
        runner.run(new MyTask()); // here you submit your task
    }
    
    
    runner.waitTillDone(); // and this blocks until all tasks are finished (or failed)
    
    
    runner.shutdown(); // once you done you can shutdown the runner
    

    You can reuse this class and call waitTillDone() as many times as you want to before calling shutdown(), plus your code is extremly simple. Also you don't have to know the number of tasks upfront.

    To use it just add this gradle/maven compile 'com.github.matejtymes:javafixes:1.3.1' dependency to your project.

    More details can be found here:

    https://github.com/MatejTymes/JavaFixes

    0 讨论(0)
  • 2020-11-22 02:37

    here is two options , just bit confuse which one is best to go.

    Option 1:

    ExecutorService es = Executors.newFixedThreadPool(4);
    List<Runnable> tasks = getTasks();
    CompletableFuture<?>[] futures = tasks.stream()
                                   .map(task -> CompletableFuture.runAsync(task, es))
                                   .toArray(CompletableFuture[]::new);
    CompletableFuture.allOf(futures).join();    
    es.shutdown();
    

    Option 2:

    ExecutorService es = Executors.newFixedThreadPool(4);
    List< Future<?>> futures = new ArrayList<>();
    for(Runnable task : taskList) {
        futures.add(es.submit(task));
    }
    
    for(Future<?> future : futures) {
        try {
            future.get();
        }catch(Exception e){
            // do logging and nothing else
        }
    }
    es.shutdown();
    

    Here putting future.get(); in try catch is good idea right?

    0 讨论(0)
  • 2020-11-22 02:38

    You could wrap your tasks in another runnable, that will send notifications:

    taskExecutor.execute(new Runnable() {
      public void run() {
        taskStartedNotification();
        new MyTask().run();
        taskFinishedNotification();
      }
    });
    
    0 讨论(0)
  • 2020-11-22 02:38

    So I post my answer from linked question here, incase someone want a simpler way to do this

    ExecutorService executor = Executors.newFixedThreadPool(10);
    CompletableFuture[] futures = new CompletableFuture[10];
    int i = 0;
    while (...) {
        futures[i++] =  CompletableFuture.runAsync(runner, executor);
    }
    
    CompletableFuture.allOf(futures).join(); // THis will wait until all future ready.
    
    0 讨论(0)
  • 2020-11-22 02:40

    Use a CountDownLatch:

    CountDownLatch latch = new CountDownLatch(totalNumberOfTasks);
    ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
    while(...) {
      taskExecutor.execute(new MyTask());
    }
    
    try {
      latch.await();
    } catch (InterruptedException E) {
       // handle
    }
    

    and within your task (enclose in try / finally)

    latch.countDown();
    
    0 讨论(0)
提交回复
热议问题