Thread.join() эквивалент в исполнителе

У меня вопрос новичков. У меня есть этот код:

public class Main 
{

    public static void main(String[] args) throws InterruptedException 
    {
        // TODO Auto-generated method stub
        IntHolder aHolder=new IntHolder();
        aHolder.Number=0;

        IncrementorThread A= new IncrementorThread(1, aHolder);
        IncrementorThread B= new IncrementorThread(2, aHolder);
        IncrementorThread C= new IncrementorThread(3, aHolder);

        A.start();
        B.start();
        C.start();

        A.join();
        B.join();
        C.join();
        System.out.println("All threads completed...");

    }

}

Которая будет ждать завершения всех потоков. Если я использую Executors следующим образом:

public class Main 
{

    public static void main(String[] args) 
    {
        // TODO Auto-generated method stub
        IntHolder aHolder=new IntHolder();
        aHolder.number=0;

        IncrementalRunable A= new IncrementalRunable(1, aHolder);
        IncrementalRunable B= new IncrementalRunable(2, aHolder);
        IncrementalRunable C= new IncrementalRunable(3, aHolder);

        ExecutorService exec = Executors.newFixedThreadPool(3);
        exec.execute(A);
        exec.execute(B);
        exec.execute(C);
        //Don't know what to do here

        System.out.println("All threads completed...");
    }
}

Как приостановить основной поток, чтобы дождаться завершения всех потоков в исполнителе, т.е. "Все потоки завершены..." должны быть напечатаны после того, как все потоки выполнили свою работу?

Ответ 1

executor.shutdown();
while (!executor.awaitTermination(24L, TimeUnit.HOURS)) {
    System.out.println("Not yet. Still waiting for termination");
}

Используйте комбинацию shutdown() + awaitTermination().

EDIT:

Основываясь на комментарии @Lital

List<Callable<Object>> calls = new ArrayList<Callable<Object>>();
calls.add(Executors.callable(new IncrementalRunable(1, aHolder)));
calls.add(Executors.callable(new IncrementalRunable(2, aHolder)));
calls.add(Executors.callable(new IncrementalRunable(3, aHolder)));

List<Future<Object>> futures = executor.invokeAll(calls);

Примечание: invokeAll() не будет возвращаться до тех пор, пока все задачи не будут завершены (либо сбой, либо завершение успешного выполнения).

Ответ 2

Вы не должны использовать такой исполнитель, если хотите дождаться завершения задач. Что делать, если вы не хотите/не можете выключить свой исполнитель пула потоков? Это более рекомендуемый способ:

    ExecutorService exec = Executors.newFixedThreadPool(3);
    Collection<Future<?>> tasks = new LinkedList<Future<?>>();

    Future<T> future = exec.submit(A);
    tasks.add(future);
    future = exec.submit(B);
    tasks.add(future);
    future = exec.submit(C);
    tasks.add(future);

    // wait for tasks completion
    for (Future<?> currTask : tasks) {
            try {
                currTask.get();
            } catch (Throwable thrown) {
                Logger.error(thrown, "Error while waiting for thread completion");
            }
        }

Ответ 3

Попробуйте работать с пулом потоков таким образом.

executor.shutdown();
executor.awaitTermination(MAX_PRIORITY, TimeUnit.HOURS);

Ответ 4

Мы можем использовать приведенный ниже код, чтобы присоединиться к ветке.

 executor.execute(new YouThread());

    try{     
         executor.shutdown();
         while (!executor.awaitTermination(24L, TimeUnit.HOURS)) {
             System.out.println("Not yet. Still waiting for termination");
         }                
    }catch(InterruptedException e){
        e.printStackTrace();
    }

Ответ 5

 exec.shutdown();
    // Wait until all threads are finish
    exec.awaitTermination();