user2862544
user2862544

Reputation: 425

what is the best way to know when all submitted tasks has been finished by Executor Service

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?

Upvotes: 1

Views: 2126

Answers (3)

Alexei Kaigorodov
Alexei Kaigorodov

Reputation: 13515

Similar to the Aris_Kortex' proposal,

List<CompletableFuture<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
    futures.add(CompletableFuture.runAsync(task, es));
}

and then create the combined CompletableFuture:

CompletableFuture<Void> cf = CompletableFuture.allOf(futures.toArray(futires.size()));

then you can wait for all tasks synchronously:

cf.get();

synchronously with timeout:

cf.get(1, TimeUnit.SECOND);

of asynchronously:

cf.thenRun(()->{finalActions();});

Upvotes: 0

Nearoo
Nearoo

Reputation: 4936

There is another way to wait for all tasks to complete. After you submitted all of your tasks, call

es.shutdown()
es.awaitTermination(Long.MAX_VALUE, TimeUnit.NANO_SECONDS)

Oracle's Java Docs read:

shutdown [...] Initiates an orderly shutdown in which previously submitted tasks are executed.

awaitTermination [...] Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.

Concerning the timeout: with the above values, the thread-pool will only terminate after about 300 years.

Upvotes: 1

akourt
akourt

Reputation: 5563

Since you effectively hold each submitted Future in a list of of futures by doing this:

List< Future<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
    futures.add(es.submit(task));
}

You can very easily check if all the submitted jobs are done executing just, by invoking the Future#isDone method, which wilkl return true or false based on whether the task has finished or not. You can check more on this on the related documentation here.

Hence, with the above in mind you could very well create a simple helper method, that will iterate the list of your futures and check on their state. For example:

private boolean areJobsDone() {
    return futures.stream()
        .allMatch(Future::isDone);
}

Note that in contrast to the Future#get method, isDone is non blocking (as it's not waiting for the task to return it's result) as it effectively queries it's state.

With this you can go ahead and check for the state of your runnables, blocking the flow with a loop that will invoke the helper method, before proceeding.

Hope this helps.

Upvotes: 3

Related Questions