I have a nice and compact code, which does not work as I expected.
public class Test {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
for (;;) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
The output is :
Timeout true
END
Question: Why does not terminate the future.cancel(true) method the called Runnable? After the program wrote the "END" to the output, the "r" Runnable is still running.
The problem is that your Runnable is not interruptible: task interruption is a collaborative process in Java and the cancelled code needs to check regularly if it's been cancelled otherwise it won't respond to the interruption.
You can amend you code as follows and it should work as expected:
Runnable r = new Runnable() {
@Override public void run() {
try {
while (!Thread.currentThread.isInterrupted()) {}
} finally {
System.out.println("FINALLY");
}
}
};