导致取消任务失败的其他原因是什么?

what's the other reasons causing fail to cancel the task?

"boolean cancel(boolean mayInterruptIfRunning) Attempts to cancel execution of this task. This attempt will fail if the task has already completed, has already been cancelled, or could not be cancelled for some other reason"

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)

除了上面列出的原因,取消任务失败还有哪些原因? 另外,如果任务 运行 代码如下,可以取消吗?

while(true)
{
;
}

实际上Java中没有终止线程的好方法。您基本上可以告诉线程停止,但线程可能一直在等待,永远不会读取标志或类似问题。这实际上是一种复杂的问题。所以我假设他们只是说 "some issue".

您 post 的 while 循环将是不可取消代码的示例,因为它不响应中断。

阻止侦听套接字的代码也可能无法处理中断。即使代码因 InterruptedIOException 超时,如果您在未设置中断标志的情况下吞下异常,则代码可能无法处理中断。

所以 TLDR:1) 阻塞 IO 的代码 2) 忽略中断如何工作的代码。或者两者结合。

每个线程都有一个保存中断状态的特殊标志,可以通过isInterrupted()方法访问。当有人中断线程时,此标志设置为 true。就这样。直到由该线程执行的代码检查该标志并抛出 InterruptedException 或如果可以的话就退出线程执行之前,不会发生真正的中断。

标准库中的许多方法旨在阻塞当前线程,实际上会不时检查此标志并在发现标志已设置时抛出 InterruptedException。例如,Thread.sleep()Thread.join()Object.wait()Lock.lockInterruptibly() 等等。因此,当您的线程定期显式检查此标志或被某些隐式检查它的描述方法阻塞时,它是可中断的。否则不是。

所以,空循环的线程不能被中断,因为它不检查中断状态。但是添加中断状态检查可以修复它:

while (!Thread.currentThread().isInterrupted()) { }

调用响应中断的方法也可以:

try {
    while (true) {
        Thread.sleep(timeout);
    }
} catch(InterruptedException e) {
    // Do nothing, just let the thread exit
}