Dnyaneshwar Pote
Dnyaneshwar Pote

Reputation: 77

How I'll get to know that, all threads in ExecutorService have finished their execution

I have created ExecutorService like:

private static final java.util.concurrent.ExecutorService EXECUTOR_SERVICE = new java.util.concurrent.ThreadPoolExecutor(
        10, // core thread pool size
        5, // maximum thread pool size
        1, // time to wait before resizing pool
        java.util.concurrent.TimeUnit.MINUTES, 
        new java.util.concurrent.ArrayBlockingQueue<Runnable>(MAX_THREADS, true),
        new java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy());

and added threads in to it with below code:

EXECUTOR_SERVICE.submit(thread);

Now I want know when all threads in EXECUTOR_SERVICE have finished their task so that I can do some dependent tasks.

Kindly suggest any way to achieve it.

Upvotes: 1

Views: 1388

Answers (4)

Trevor Freeman
Trevor Freeman

Reputation: 7242

Without modifying your submitted tasks, you are left to either query the internal state of ThreadPoolExecutor, subclass ThreadPoolExecutor to track task completion according to your requirements, or collect all of the returned Futures from task submission and wait on them each in turn until they are all done.

In no particular order:

Option 1: Query the state of ThreadPoolExecutor:

You can use ThreadPoolExecutor.getActiveCount() if you keep your reference typed to ThreadPoolExecutor instead of ExecutorService.

From ThreadPoolExecutor source:

/**
 * Returns the approximate number of threads that are actively executing tasks.
 * Returns:
 *   the number of threads
 **/

public int getActiveCount() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        int n = 0;
        for (Worker w : workers)
            if (w.isLocked())
                ++n;
        return n;
    } finally {
        mainLock.unlock();
    }
}

The JavaDoc there that mentions "approximate" should concern you, however, since given concurrent execution it is not necessarily guaranteed to be accurate. Looking at the code though, it does lock and assuming it is not queried in another thread before all of your tasks have been added, it appears to be sufficient to test for task completeness.

A drawback here is that you are left to monitor the value continuously in a check / sleep loop.

Option 2: Subclass ThreadPoolExecutor:

Another solution (or perhaps a complementary solution) is to subclass ThreadPoolExecutor and override the afterExecute method in order to keep track of completed executions and take appropriate action. You could design your subclass such that it will call a callback once X tasks have been completed, or the number of remaining tasks drops to 0 (some concurrency concerns there since this could trigger before all tasks have been added) etc.

Option 3: Collect task Futures (probably the best option):

Each submission to the ExecutorService returns a Future which can be collected in a list. A loop could then run through and wait on each future in turn until all tasks are complete.

E.g.

List<Future> futures = new ArrayList<Future>();
futures.add(executorService.submit(myTask1));
futures.add(executorService.submit(myTask2));

for (Future future : futures) {
    // TODO time limit, exception handling, etc etc.
    future.get();
}

Upvotes: 0

Jose Martinez
Jose Martinez

Reputation: 12022

Use CountDownLatch. I have used this before in the past with great success.

A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

The Javadoc link has a great example.

Upvotes: 2

Ciro Rizzo
Ciro Rizzo

Reputation: 492

You could use :

try  {
  executor.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
  // Report the interruptedException
}

Upvotes: 2

Ankush soni
Ankush soni

Reputation: 1459

As per Java Doc Signature of submit Method is <T> Future<T> submit(Callable<T> task)

and

Submits a value-returning task for execution and returns a Future representing the pending results of the task. The Future's get method will return the task's result upon successful completion. If you would like to immediately block waiting for a task, you can use constructions of the form result = exec.submit(aCallable).get();

Note: The Executors class includes a set of methods that can convert some other common closure-like objects, for example, PrivilegedAction to Callable form so they can be submitted.

which return

Future representing pending completion of the task

Upvotes: 1

Related Questions