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

前端 未结 26 2001
你的背包
你的背包 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:40

    ExecutorService.invokeAll() does it for you.

    ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
    List<Callable<?>> tasks; // your tasks
    // invokeAll() returns when all tasks are complete
    List<Future<?>> futures = taskExecutor.invokeAll(tasks);
    
    0 讨论(0)
  • 2020-11-22 02:40

    You can use Lists of Futures, as well:

    List<Future> futures = new ArrayList<Future>();
    // now add to it:
    futures.add(executorInstance.submit(new Callable<Void>() {
      public Void call() throws IOException {
         // do something
        return null;
      }
    }));
    

    then when you want to join on all of them, its essentially the equivalent of joining on each, (with the added benefit that it re-raises exceptions from child threads to the main):

    for(Future f: this.futures) { f.get(); }
    

    Basically the trick is to call .get() on each Future one at a time, instead of infinite looping calling isDone() on (all or each). So you're guaranteed to "move on" through and past this block as soon as the last thread finishes. The caveat is that since the .get() call re-raises exceptions, if one of the threads dies, you would raise from this possibly before the other threads have finished to completion [to avoid this, you could add a catch ExecutionException around the get call]. The other caveat is it keeps a reference to all threads so if they have thread local variables they won't get collected till after you get past this block (though you might be able to get around this, if it became a problem, by removing Future's off the ArrayList). If you wanted to know which Future "finishes first" you could use some something like https://stackoverflow.com/a/31885029/32453

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

    In Java8 you can do it with CompletableFuture:

    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();
    
    0 讨论(0)
  • 2020-11-22 02:43

    Java 8 - We can use stream API to process stream. Please see snippet below

    final List<Runnable> tasks = ...; //or any other functional interface
    tasks.stream().parallel().forEach(Runnable::run) // Uses default pool
    
    //alternatively to specify parallelism 
    new ForkJoinPool(15).submit(
              () -> tasks.stream().parallel().forEach(Runnable::run) 
        ).get();
    
    0 讨论(0)
  • 2020-11-22 02:44

    There is a method in executor getActiveCount() - that gives the count of active threads.

    After spanning the thread, we can check if the activeCount() value is 0. Once the value is zero, it is meant that there are no active threads currently running which means task is finished:

    while (true) {
        if (executor.getActiveCount() == 0) {
        //ur own piece of code
        break;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 02:46

    This is my solution, based in "AdamSkywalker" tip, and it works

    package frss.main;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class TestHilos {
    
        void procesar() {
            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();
    
            System.out.println("FIN DEL PROCESO DE HILOS");
        }
    
        private List<Runnable> getTasks() {
            List<Runnable> tasks = new ArrayList<Runnable>();
    
            Hilo01 task1 = new Hilo01();
            tasks.add(task1);
    
            Hilo02 task2 = new Hilo02();
            tasks.add(task2);
            return tasks;
        }
    
        private class Hilo01 extends Thread {
    
            @Override
            public void run() {
                System.out.println("HILO 1");
            }
    
        }
    
        private class Hilo02 extends Thread {
    
            @Override
            public void run() {
                try {
                    sleep(2000);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("HILO 2");
            }
    
        }
    
    
        public static void main(String[] args) {
            TestHilos test = new TestHilos();
            test.procesar();
        }
    }
    
    0 讨论(0)
提交回复
热议问题