Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if all tasks running on ExecutorService are completed

I'v got ConcurrentLinkedDeque which I'm using for synchronic push/pop elements, and I'v got some async tasks which are taking one element from stack and if this element has neighbors It's pushing it to stack.

Example code:

private ConcurrentLinkedDeque<Item> stack = new ConcurrentLinkedDeque<>(); private ExecutorService exec = Executors.newFixedThreadPool(5);      while ((item = stack.pollFirst()) != null) {                 if (item == null) {                 } else {                     Runnable worker = new Solider(this, item);                     exec.execute(worker);                 }             }     class Solider{          public void run(){              if(item.hasNeighbors){                 for(Item item:item.neighbors){                     stack.push(item)                 }              }           }     } 

I would like to have additional statement in while loop which answers the question - "any task in Executor is working?"

like image 372
user4129715 Avatar asked Nov 21 '15 15:11

user4129715


People also ask

Which method of ExecutorService is called to check that all tasks are complete following shutdown?

When using an Executor, we can shut it down by calling the shutdown() or shutdownNow() methods. Although, it won't wait until all threads stop executing. Waiting for existing threads to complete their execution can be achieved by using the awaitTermination() method.

Which method provided by ExecutorService is used to check whether job is finished or Cancelled?

The Java ExecutorService submit(Runnable) method also takes a Runnable implementation, but returns a Future object. This Future object can be used to check if the Runnable has finished executing.

How do I get an ExecutorService result?

This can be done by submitting a Callable task to an ExecutorService and getting the result via a Future object. The purpose of the Callable interface is similar to Runnable, but its method returns a value of type T. Integer value = result. get();

How do I stop all threads in ExecutorService?

Using shutdownNow() The shutdownNow() is a hard signal to destroy ExecutorService immediately along with stopping the execution of all in-progress and queued tasks. Use this method, when we want the application to stop processing all tasks immediately.


2 Answers

There isn't a clean way to check if all Runnables are done if you use ExecutorService.execute(Runnable). Unless you build a mechanism to do so in the Runnable itself (which is sloppy in my opinion).

Instead:
Use ExecutorService.submit(Runnable). This method will return a Future<?> which is a handle to the result of a Runnable. Using Futures provides a clean way to check results.

All you have to do is maintain a list of Futures that you submit, and then you can iterate over the whole list of Futures and either:
  A) wait for all the futures to be done in a blocking way or
  B) check if all the futures are done in a non-blocking way.

Here is a code example:

List<Future<?>> futures = new ArrayList<Future<?>>(); ExecutorService exec = Executors.newFixedThreadPool(5);  // Instead of using exec.execute() use exec.submit() // because it returns a monitorable future while((item = stack.pollFirst()) != null){     Runnable worker = new Solider(this, item);     Future<?> f = exec.submit(worker);     futures.add(f); }  // A) Await all runnables to be done (blocking) for(Future<?> future : futures)     future.get(); // get will block until the future is done  // B) Check if all runnables are done (non-blocking) boolean allDone = true; for(Future<?> future : futures){     allDone &= future.isDone(); // check if future is done } 
like image 91
Andy Guibert Avatar answered Oct 07 '22 23:10

Andy Guibert


Update: with Java 8+ CompletableFutures you can manage this with its new callback functions. First you will need to create all of the CompletableFutures you need which will also start running, eg:

We need to accumulate all the futures generated in an Array in order to pass them later to CompletableFuture.allOf(CompletableFutures...)

So let's say you have a list of people you want to calculate its days until birthday asynchronously:

First we create all those needed futures and collect them together in an array:

CompletableFuture<?>[] completables = people.stream()     .map(p -> createCompletableFuture(p))     .toArray(CompletableFuture<?>[]::new);  private CompletableFuture createCompletableFuture(Person p) {         return CompletableFuture.runAsync(daysUntillBirthday(p));     } 

Then you pass those completables to a new CompletableFuture:

CompletableFuture c = CompletableFuture.allOf(completables) 

And you can now check if there are still futures running with:

c.isDone() 
like image 20
Carlos Sanchez Avatar answered Oct 07 '22 21:10

Carlos Sanchez