【问题标题】:How does interrupting a future work with single thread executors?单线程执行器如何中断未来的工作?
【发布时间】:2017-09-15 15:45:33
【问题描述】:

如果我经常安排要运行的任务被 future.cancel(true); 取消,Executor.newSingleThreadExecutor() 的行为如何?

executor产生的单线程是否被中断(因此future代码需要清除中断),还是在下一个future启动时中断标志自动清除。

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

有没有更好的办法?

【问题讨论】:

  • Future,你调用cancel,通常是一个FutureTask,它已经在执行后处理清除取消中断。万一,中断发生在任务运行时。否则,执行者的线程根本不会被中断。

标签: java multithreading future executor


【解决方案1】:

好问题,我在任何地方都没有发现这方面的记录,所以我会说它依赖于实现。

例如,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 的片段。

【讨论】:

    【解决方案2】:

    下面的示例程序演示了如果使用 true 调用取消方法,则会在线程上调用中断。您甚至可以看到它正在重用同一个线程。取消返回一个布尔值,指示取消是否成功。这个方法的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
    

    【讨论】:

    • 为编写测试而喝彩。但是,这不会测试在任务未清除中断标志的情况下的行为,这是 OP 所要求的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 2018-04-12
    • 2018-10-02
    相关资源
    最近更新 更多