Reputation: 77
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
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 Future
s 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
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
Reputation: 492
You could use :
try {
executor.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// Report the interruptedException
}
Upvotes: 2
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