views:

272

answers:

2

I have a series of concurrent tasks to run. If any one of them fails, I want to interrupt them all and await termination. But assuming none of them fail, I want to wait for all of them to finish.

ExecutorCompletionService seems like almost what I want here, but there doesn't appear to be a way to tell if all of my tasks are done, except by keeping a separate count of the number of tasks. (Note that both of the examples of in the Javadoc for ExecutorCompletionService keep track of the count "n" of the tasks, and use that to determine if the service is finished.)

Am I overlooking something, or do I really have to write this code myself?

+1  A: 

Yes, you do need to keep track if you're using an ExecutorCompletionService. Typically, you would call get() on the futures to see if an error occurred. Without iterating over the tasks, how else could you tell that one failed?

Jeff Storey
He could handle the error condition in the task, but yeah, calling get() on the Future is best.
Tim Bender
I do need to iterate over the tasks of course, but I can just take() the futures from the ExecutorCompletionService. (This is what the Javadoc example does.) The problem is that I can't just take() until I run out of tasks, because if I take() when there's no work left, I'll be stuck waiting forever.
Dan Fabulich
Right, so you need to precalculate the number of tasks (as you thought), and take that many times.
Jeff Storey
+1  A: 

If your series of tasks is of a known size, then you should use the second example in the javadoc.

However, if you don't know the number of tasks which you will submit to the CompletionService, then you have a sort of Producer-Consumer problem. One thread is producing tasks and placing them in the ECS, another would be consuming the task futures via take(). A shared Semaphore could be used, allowing the Producer to call release() and the Consumer to call acquire(). Completion semantics would depend on your application, but a volatile or atomic boolean on the producer to indicate that it is done would suffice.

I suggest a Semaphore over wait/notify with poll() because there is a non-deterministic delay between the time a task is produced and the time that task's future is available for consumption. Therefore the consumer and producer needs to be just slightly smarter.

Tim Bender
Actually, in my case, I just have one main thread producing the tasks and consuming the futures. I can certainly have that thread keep deterministic track of the count of tasks, but it seems odd that I should have to.
Dan Fabulich