When is an ExecutorService idle?

I have a number of JUnit tests that trigger some complex behaviour involving additional background threads managed by an ExecutorService (in fact a ThreadPoolExecutor). The application should settle down to a well-defined state when the background tasks have been completed, i.e. the ExecutorService is idle because all submitted tasks have been processed and terminated. The problem is that there doesn't seem to be any reliable way to check for this condition. This means that I can't decide when to check for the 'well-defined state'.

Basically I need anisIdle() method which can be used to wait until all submitted requests have been completed. Since there doesn't seem to be any single method that does this I tried to combine all of the methods that looked likely:

publicboolean isIdle(){

return ((requestExecutor.getQueue().size() == 0) &&

(requestExecutor.getTaskCount() == requestExecutor.getCompletedTaskCount()) &&

(requestExecutor.getActiveCount() == 0));

}

but that still doesn't seem to work. Sometimes it seems to return true even when there are still tasks floating around. If you read the relevant javadoc with it's strong caveats about "the returned value is only an approximation" then perhaps that is not so surprising. Is there areliable way to tell whether an ExecutorService is idle? Shutting it down and waiting for it to terminate is not an option!

The only alternative is to go to sleep for a while and hope that everything is finished afterwards but this leads to JUnit tests that are either slow or error-prone (how big should the sleep be?).

[1817 byte] By [SwissArmyKnifea] at [2007-11-26 21:35:37]
# 1

It seems that, the best way to solve your problem is to:

- store all FutureTasks submitted to the Executor;

- call the FutureTask's get method on each task saved.

If there are tasks not yet terminated, the get method

will block your thread until all tasks will be done.

Hope this help

CanapaGa at 2007-7-10 3:16:15 > top of Java-index,Core,Core APIs...
# 2

There is no way to tell I'm afraid. If you query between a worker thread taking a task from the queue (q.size()==0) but before it updates activeCount (activeCount==0) then you'll get the wrong answer from isIdle().

Can't you check for the completion of those background tasks explicitly?

davidholmesa at 2007-7-10 3:16:15 > top of Java-index,Core,Core APIs...
# 3

The problem is that the background tasks can be created anywhere in the application and are supposed to be asynchronous. Since they are asynchronous there is no place in the code that waits for them to finish, which means that there is nowhere that I can add a check for completion or to clean up a task list.

I'm sure that I could write a wrapper that could manage this somehow, but that is likely to be excessively complex for something that is only needed in the JUnit tests (at the moment). It's just annoying because this functionality could be implemented fairly easily within the ExecutorService itself. Of course I could write my own ExecutorService from scratch but that rather defeats the object of having library classes...

It sounds as though this wasn't planned and isn't possible with the existing interface.

SwissArmyKnifea at 2007-7-10 3:16:15 > top of Java-index,Core,Core APIs...
# 4

Nope it wasn't planned functionality. It also isn't easy to implement without providing locks where they otherwise aren't needed. As you point out the state of being "idle" is actually a composite state - all threads blocked and the queue is empty.

A wrapper that tracks your own "completion count" might suffice for your purposes.

davidholmesa at 2007-7-10 3:16:15 > top of Java-index,Core,Core APIs...