你能想一想为什么这段代码不起作用而且总是输出"完成",但是第二个例子没有任何问题。我使用的是最新的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); } }
编辑:添加了返回和更新的睡眠时间以及另一个示例。
答案 0 :(得分:4)
这比我原先想象的要简单。问题是工作窃取池在内部使用ForkJoinPool而ForkJoinTask不支持cancel(true),因此在任务启动后无法取消任务。
请参阅javadoc文档(http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html):
mayInterruptIfRunning - this value has no effect in the default implementation
because interrupts are not used to control cancellation.
答案 1 :(得分:2)
无法用Java强制终止Thread。 (二十年前,Java 1.0试图提供这一点,结果证明它是行不通的;尝试这样做的方法已被弃用,没有替换。)
作为Runnable的作者,您有责任通过干净地终止自己的run
方法来正确响应中断。在你的情况下,你应该在catch-block中退出run
方法,但你没有;你让方法的逻辑继续超过catch-block。因此,即使线程被中断,也始终执行run
方法的最后一个语句。