为什么FutureTask不再在内部使用AQS?

Ale*_*tin 3 java java-8

为什么在jdk8中,相对于jdk7,FutureTask在内部不再使用AQS?

据说在jdk 8评论中它已经完成:“避免让用户感到惊讶,因为他们在取消比赛期间保留了中断状态”

我想了解更多有关该用例的信息,如果有一个不良行为的例子,此更改将得以解决。

Hol*_*ger 5

请考虑以下情形:

  • 线程A run()FutureTask
  • 线程B调用cancel(true),成功将状态从切换RUNNINGCANCELLED(在Java 8之前)
  • 线程A完成该run()方法
  • 仍在内部的线程B cancel(true)中断线程
  • 线程A(现在不在线程中)FutureTask被虚假中断

新设计通过为INTERRUPTING尝试中断线程之前设置,和INTERRUPTED之后设置的不同状态来解决此问题。然后,在完成时调用以下方法:

/**
 * Ensures that any interrupt from a possible cancel(true) is only
 * delivered to a task while in run or runAndReset.
 */
private void handlePossibleCancellationInterrupt(int s) {
    // It is possible for our interrupter to stall before getting a
    // chance to interrupt us.  Let's spin-wait patiently.
    if (s == INTERRUPTING)
        while (state == INTERRUPTING)
            Thread.yield(); // wait out pending interrupt
…
Run Code Online (Sandbox Code Playgroud)

请注意,这仍然不会重置线程的中断状态。这仍然是调用者的职责,例如ExecutorService实施。但是现在可以保证在取消的情况下,从该run()方法返回时已经完成了潜在的中断,因此很容易重置标志。没有这种保证,在取消取消授权的情况下,可能会在尝试重置中断状态之后发生中断。