问题
I'm using a ScheduledExecutorService
to close a network connection if it has been open for more than several hours. In most cases however, the network connection is closed before the timeout is reached, so I cancel the ScheduledFuture
. In this case, I also want the executor service to terminate and to release its thread pool.
To my surprise, this does not work out of the box: Although I have called shutdown()
on the executor service after scheduling the task, the executor service does not terminate automatically when its only scheduled task is cancelled. From the JavaDoc of ExecutorService.shutdown()
this behaviour may even be correct because arguably the cancelled task has not been "executed":
void java.util.concurrent.ExecutorService.shutdown()
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
My question is if this can be changed: Is it possible to configure an executor service to automatically terminate when its only scheduled task is cancelled?
Or the same question written as a JUnit test:
@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:
From the ScheduledThreadPoolExecutor
(the actual type returned by Executors.newScheduledThreadPool
) documentation:
When a submitted task is cancelled before it is run, execution is suppressed. By default, such a cancelled task is not automatically removed from the work queue until its delay elapses. While this enables further inspection and monitoring, it may also cause unbounded retention of cancelled tasks. To avoid this, set setRemoveOnCancelPolicy(boolean) to true, which causes tasks to be immediately removed from the work queue at time of cancellation.
This is a ScheduledThreadPoolExecutor
method though. I don't believe it's possible to solve this purely using the ScheduledExecutorService
interface.
来源:https://stackoverflow.com/questions/23369952/how-to-make-a-scheduledexecutorservice-terminate-automatically-when-its-schedule