ExecutorService workStealingPool 和取消方法

ExecutorService workStealingPool and cancel method

你能想出为什么这段代码不工作并总是输出 "finished" 的任何原因,但第二个例子没有任何问题。我正在使用最新的 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);
        }
    }

编辑:添加 return 并更新了睡眠时间和另一个示例。

无法强制终止 Java 中的线程。 (二十年前,Java 1.0 试图提供这一点,但结果证明是行不通的;尝试这样做的方法已被弃用,没有替代品。)

作为 Runnable 的作者,您有责任通过干净地终止您自己的 run 方法来正确响应中断。在你的例子中,你应该在 catch 块中退出你的 run 方法,但你没有;您让方法的逻辑继续通过 catch 块。所以即使线程被中断,run方法的最后一条语句总是被执行。

比我原来想的要简单。问题是 work-stealing-pool 在内部使用 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.