你能想一想这个代码不起作用的任何原因并且总是输出“完成”,但第二个例子没有任何问题 . 我正在使用最新的JDK(8u45) .
public static class MyClass implements Runnable {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
System.out.println("Interrupted");
return;
}
System.out.println("Finished");
}
public static void main(String[] args) {
// spot the difference ->
ExecutorService executorService = Executors.newWorkStealingPool(4);
Future future = executorService.submit(new MyClass());
Thread.sleep(100);
future.cancel(true);
}
}
以下示例完美无缺:
public static class MyClass implements Runnable {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
System.out.println("Interrupted");
return;
}
System.out.println("Finished");
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future future = executorService.submit(new MyClass());
Thread.sleep(100);
future.cancel(true);
}
}
编辑:添加了返回和更新的睡眠时间和另一个例子 .
2 回答
它比我原先想象的要简单 . 问题是工作窃取池在内部使用ForkJoinPool而ForkJoinTask不支持cancel(true),因此在任务启动后无法取消任务 .
请参阅javadoc文档(http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html):
没有办法强制终止Java中的线程 . (二十年前,Java 1.0尝试提供此功能,结果证明它不可行;尝试执行此操作的方法已弃用,无需替换 . )
作为Runnable的作者,您有责任通过干净地终止自己的
run
方法来正确响应中断 . 在你的情况下,你应该退出catch块中的run
方法,但是你没有't; you let the method'的逻辑继续通过catch-block . 因此,即使线程被中断,run
方法的最后一个语句也始终执行 .