如何使ScheduledExecutorService在其计划任务被取消时自动终止

时间:2014-04-29 16:12:58

标签: java multithreading concurrency java.util.concurrent

如果网络连接已打开超过几个小时,我正在使用ScheduledExecutorService关闭网络连接。但是,在大多数情况下,网络连接在达到超时之前关闭,因此我取消ScheduledFuture。在这种情况下,我还希望执行程序服务终止并释放其线程池。

令我惊讶的是,这并不是开箱即用的:尽管我在调度任务后在执行程序服务上调用了shutdown(),但执行程序服务在其唯一的计划任务被取消时不会自动终止。从ExecutorService.shutdown()的JavaDoc来看,这种行为甚至可能是正确的,因为可以说已取消的任务尚未“执行”:

  

void java.util.concurrent.ExecutorService.shutdown()

     

启动有序关闭,其中先前提交的任务已执行,但不会接受任何新任务。如果已经关闭,调用没有额外的效果。

我的问题是,是否可以更改:是否可以将执行程序服务配置为在其唯一的计划任务被取消时自动终止?


或者写成JUnit测试的同一个问题:

@Test
public void testExecutorServiceTerminatesWhenScheduledTaskIsCanceled() throws Exception {
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    Runnable task = new Runnable() {
        @Override
        public void run() {
            // ...
        }
    };

    ScheduledFuture<?> scheduledTask = scheduler.schedule(task, 2000, TimeUnit.MILLISECONDS);
    scheduler.shutdown();
    // do more configuration here...

    Thread.sleep(1000);

    scheduledTask.cancel(false);

    Thread.sleep(100);
    assertThat(scheduler.isTerminated(), is(true)); // ... so that this passes!?
}

1 个答案:

答案 0 :(得分:4)

来自ScheduledThreadPoolExecutorExecutors.newScheduledThreadPool返回的实际类型)文档:

  

在提交的任务在运行之前被取消时,将禁止执行。默认情况下,此类已取消的任务不会自动从工作队列中删除,直到其延迟结束。虽然这可以进一步检查和监控,但也可能导致取消任务的无限制保留。要避免这种情况,请将setRemoveOnCancelPolicy(boolean)设置为true,这会导致在取消时立即从工作队列中删除任务。

这是ScheduledThreadPoolExecutor方法。我不相信可以使用ScheduledExecutorService接口完全解决这个问题。