我必须在 FutureTask 中手动处理中断吗?

Do I have to manually process interrupt in FutureTask?

我目前正在尝试了解 FutureTask.cancel(true) 是如何工作的,这是官方文档的相关部分

If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.

这是 cancel 的实现,取自 Github

public boolean cancel(boolean mayInterruptIfRunning) {
    if (!(state == NEW &&
          UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
              mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
        return false;
    try {    // in case call to interrupt throws exception
        if (mayInterruptIfRunning) {
            try {
                Thread t = runner;
                if (t != null)
                    t.interrupt();
            } finally { // final state
                UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
            }
        }
    } finally {
        finishCompletion();
    }
    return true;
}

所以,基本上我们可以看到 cancel(true) 唯一做的就是在工作线程上调用 interrupt。那么,如果我的 FutureTaskcall 方法看起来像这样

怎么办?
SomeType call() {
  for(int i = 0; i < 1000000000; i++) {
    //pass
  }
  return someValue;
}

所以,我的问题 - 我是否必须添加手动检查线程中断才能取消此类 FutureTasks?我的意思是这似乎很明显,因为我没有调用任何可以处理中断的 IO 函数并且没有检查 Thread.currentThread().isInterrupted(),所以这个任务似乎是不可取消的,但在我们拥有的任何官方文档中仍然没有提到处理中断或自己能够取消任务,所以最好还是征求别人的意见。

是的,你要处理CancellationException(这个异常抛出FutureTask.get()方法),如果你不处理,这个异常就会抛给JVM。看一遍这个例子,会输出“Task is canceled”:

public class MainTest {
    public static void main(String... args) {
        FutureTask<Long> futureTask = new FutureTask<>(new MyCallable());

        ExecutorService executorService = Executors.newFixedThreadPool(1);
        executorService.submit(futureTask);

        try {
            futureTask.cancel(true);
            System.out.println(futureTask.get());
        } catch (CancellationException e) {
            System.out.println("Task is canceled");
        } catch (InterruptedException | ExecutionException e) {
            System.out.println("Something went wrong!");
        }

        executorService.shutdown();
    }
}

class MyCallable implements Callable<Long> {
    @Override
    public Long call() {
        for(int i = 0; i < 1000000000; i++) {
            //pass
        }

        return 1L;
    }
}

Java 中没有先发制人。对于任何可中断的事物,它都必须合作。所以是的,任务必须检查它是否被中断,否则它会 运行 直到结束,尽管未来被取消了。令人失望,我知道。