中断未来如何与单线程执行者一起工作?

How does interrupting a future work with single thread executors?

如果我经常将任务安排到 运行 并且正在被 future.cancel(true); 取消,Executor.newSingleThreadExecutor() 会如何表现?

执行器产生的单个线程是否被中断(因此未来的代码需要清除中断),或者中断标志是否在下一个未来启动时自动清除。

Executor 是否需要在每个中断上生成一个额外的线程以供剩余的任务队列使用?

有没有更好的方法?

下面的示例程序演示了如果调用cancel方法为true,则在线程上调用中断。您甚至可以看到它正在重用同一个线程。取消 returns 一个布尔值,指示取消是否成功。这个方法的javadoc也很清楚

class Task implements Callable<String> {

    @Override
    public String call() throws Exception {
        try {
            System.out.println("Thread name = " + Thread.currentThread().getName());
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            System.out.println("Interrupted");
            return "Interruped";
        }
        return "X";
    }
}
public class Testy {


    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService =
                Executors.newSingleThreadExecutor();
        int count = 0;
        while (true) {
            System.out.println("Iteration " + count++);
            Future<String> submit = executorService.submit(new Task());
            Thread.sleep(500);
            submit.cancel(true);
        }

    }
}

输出如下所示

Iteration 0
Thread name = pool-1-thread-1
Iteration 1
Interrupted
Thread name = pool-1-thread-1
Iteration 2
Interrupted

好问题,我没有在任何地方找到这个记录,所以我会说它取决于实现。

例如 OpenJDK 会在每次执行任务之前重置中断标志:

// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted.  This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
     (Thread.interrupted() &&
      runStateAtLeast(ctl.get(), STOP))) &&
    !wt.isInterrupted())
    wt.interrupt();

来自 OpenJDK jdk8u ThreadPoolExecutor#runWorker source 的片段。