I want to manage a list of Futures objects returned by my TaskExecutor.
I've something like this
List<Future<String>> list
void process(ProcessThis processThis) {
for ( ...) {
Future<String> future = taskExecutor.submit(processThis);
list.add(future)
}
}
void removeFutures() {
for(Future future : list) {
assert future.cancel(true);
}
ProcessThis is a task that implements Callable< String> and checks for Thread.interrupted() status
public String call() {
while (true) {
if (Thread.interrupted()) {
break;
}
doSomething();
}
}
Now the problem is that only a subset of the concurrent Threads is returning 'true' when Thread.interrupted() is called.
The assert in removeFutures() returns true for every future that is removed (I checked isDone() and isCompleted() as well.
The number of Threads that are interrupted is random. Over 15 running Threads sometimes 13 are interrupted, sometimes 2 ...
I really don't understand where's the issue. if I call future.cancel(true) and this returns true... and then I check Thread.interrupted (this is called only once), I expect this to return true as well.
Any idea of what am I missing?
I'm on build java 1.6.0_02-b05
At least, you should restore the interruption flag to make taskExecutor aware of the thread interruption:
A potential problem that interrupts are often swallowed. So somewhere deep in
doSomething()
(or even in class loading), an interrupt may be caught by, say,wait()
and then discarded by 'careless' code. Interrupts are evil, IMO.It may be worth checking that all of you tasks are actually running at the time of the cancel.
Be aware that
Thread.interrupted()
returns the current interrupted status and then clears it, so all future invocations will return false. What you want is probablyThread.currentThread().isInterrupted()
.Also be aware that
future.cancel(true)
will usually only return false if the task had already been completed or canceled. If it returns true, that is no guarantee that the task will actually be canceled.What is happening in
doSomething()
? Its possible that a RuntimeException is escaping somewhere due to the interrupt. Do you have an UncaughtExceptionHandler set? If not, you'll need to pass a ThreadFactory to theExecutor
that will set the exception handler and log any missed exceptions.