ExecutorService workStealingPool和取消方法
你能想一想为什么这段代码不起作用,总是输出“完成”,但第二个例子没有任何问题。 我正在使用最新的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); } }
编辑:增加了返回和更新的睡眠时间,另一个例子。
这比我原来想象的更简单。 问题在于工作窃取池在内部使用ForkJoinPool,而ForkJoinTask不支持取消(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.
没有办法强行终止Java中的Thread。 (二十年前,Java 1.0试图提供这一点,结果证明它是行不通的;试图实现它的方法已被弃用,没有替换。)
您作为Runnable的作者,负责通过干净地终止您自己的run
方法来正确响应中断。 就你而言,你应该已经在catch-block中退出了run
方法,但是你没有; 你让方法的逻辑继续超越catch-block。 所以即使线程被中断, run
方法的最后一条语句也会被执行。