Reputation: 1379
The javadoc says invokeAll(Collection<> callables)
throws
InterruptedException - if interrupted while waiting, in which case unfinished tasks are cancelled
but there is no documentation on why the call could be interrupted. My program does so - but very rarely and I can not write a test that would cause it to happen.
I'm using the one parameter method without a timeout.
public class ParallelUtil<T> {
public interface Task<T> {
public void execute(T data) throws Exception;
}
public void execute(final Task<T> task, Collection<T> targets) {
ExecutorService executor = null;
try {
executor = Executors.newFixedThreadPool(20);
execute(task, targets, executor);
} finally {
if (executor != null) {
try {
executor.shutdown();
} catch (Exception e) {}
}
}
}
private void execute(final Task<T> task, Collection<T> targets, ExecutorService executor) {
List<Callable<Void>> tasks = new ArrayList<>();
...
try {
executor.invokeAll(tasks);
} catch (Exception e) {
// Here we get InterruptedException - for no reason?
// With some of the tasks left undone!
}
}
}
InterruptedException is thrown (at least in some cases) from java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400)
There can be many of these ParallelUtils
running at the same time (launched from different threads), but as you can see each call creates its own ExecutorService
, so they should not mess each other.
(As a side question could I use a shared pool for all calls without the invokeAll calls messing each other?)
Upvotes: 2
Views: 4073
Reputation: 5052
There can be many of these ParallelUtils running at the same time (launched from different threads)
Apparently at least one of these threads is interrupted either directly via Thread.interrupt()
or indirectly via e.g. Future.cancel(true)
or ExecutorService.shutdownNow()
.
Example to reproduce this interrupt:
class Sleep implements ParallelUtil.Task<Integer> {
@Override
public void execute(Integer data) throws Exception {
Thread.sleep(Long.MAX_VALUE);
}
}
class InterruptInvokeAll {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(
() -> {
ParallelUtil<Integer> parallelUtil = new ParallelUtil<>();
parallelUtil.execute(new Sleep(), Arrays.asList(1));
});
executorService.shutdownNow(); // indirectly interrupts thread that calls executor.invokeAll
}
}
Upvotes: 2
Reputation: 719446
What can cause
ExecutorService.invokeAll()
to throw anInterruptedException
?
See the javadoc for shutdownNow()
:
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via
Thread.interrupt()
, so any task that fails to respond to interrupts may never terminate.
Since invokeAll
waits until all tasks in the have been completed, calling shutdownNow()
from another thread is one way that an invokeAll
call could be interrupted.
However, in the code as you have shown it to us, there are no calls to shutdownNow()
and no obvious way for the executor service object to leak to another thread.
It is also possible that something in your code (or some other library code) is calling Thread.interrupt
. For example, one of the tasks might be doing this to itself.
Upvotes: 2