从 ScheduledExecutorService 停止和删除任务
Stopping and removing a task from ScheduledExecutorService
我知道我可以抛出异常来禁止进一步执行已安排在 ScheduledExecutorService 中重复执行的任务(请参阅 this question)。
我也知道我可以 setRemoveOnCancelPolicy(true) 来确保已取消的任务从队列中删除。
我的问题是:当我从其中抛出异常时,任务是否真的也从调度程序中删除了?这是否通过隐式取消未来发生?如果是,这是否意味着 setRemoveOnCancelPolicy() 也适用于这种情况?
在 Javadocs 中找不到任何内容。
我也有同样的疑问,在文档中找不到任何内容,所以我试了一下。观察:
- 投掷
RuntimeException
将未来标记为 完成,未取消。
Runnable
已从调度程序的队列中删除,不管 的 setRemoveOnCancelPolicy()
。
亲自尝试一下:
public class SchedulerTest {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
@Test
public void schedulerExecutionException() throws Exception {
log.info("Test: schedulerExecutionException");
ScheduledThreadPoolExecutor sched = new ScheduledThreadPoolExecutor(2);
sched.setRemoveOnCancelPolicy(true);
ScheduledFuture future1 = sched.scheduleAtFixedRate(new Runnable() {
int counter = 0;
@Override
public void run() {
log.info("Runnable 1: "+ ++counter);
if (counter >= 2) {
log.info("Runnable 1: BOOOM");
throw new RuntimeException("boom");
}
}
}, 1, 1, TimeUnit.SECONDS);
ScheduledFuture future2 = sched.scheduleAtFixedRate(new Runnable() {
int counter = 0;
@Override
public void run() {
log.info("Runnable 2: "+ ++counter);
}
}, 1, 1, TimeUnit.SECONDS);
long cutoff = new Date().getTime() + 6000;
while (new Date().getTime() < cutoff) {
log.info("Scheduler Queue size: "+ sched.getQueue().size());
log.info("Future 1: is "+ (future1.isCancelled() ? "" : "not ") +"cancelled, is "+ (future1.isDone()? "" : "not ") +"done");
log.info("Future 2: is "+ (future2.isCancelled() ? "" : "not ") +"cancelled, is "+ (future2.isDone()? "" : "not ") +"done");
Thread.sleep(1000);
}
assertEquals(sched.getQueue().size(), 1);
future2.cancel(true);
log.info("Scheduler Queue size: "+ sched.getQueue().size());
log.info("Future 1: is "+ (future1.isCancelled() ? "" : "not ") +"cancelled, is "+ (future1.isDone()? "" : "not ") +"done");
log.info("Future 2: is "+ (future2.isCancelled() ? "" : "not ") +"cancelled, is "+ (future2.isDone()? "" : "not ") +"done");
assertEquals(sched.getQueue().size(), 0);
sched.shutdownNow();
}
}
我知道我可以抛出异常来禁止进一步执行已安排在 ScheduledExecutorService 中重复执行的任务(请参阅 this question)。
我也知道我可以 setRemoveOnCancelPolicy(true) 来确保已取消的任务从队列中删除。
我的问题是:当我从其中抛出异常时,任务是否真的也从调度程序中删除了?这是否通过隐式取消未来发生?如果是,这是否意味着 setRemoveOnCancelPolicy() 也适用于这种情况?
在 Javadocs 中找不到任何内容。
我也有同样的疑问,在文档中找不到任何内容,所以我试了一下。观察:
- 投掷
RuntimeException
将未来标记为 完成,未取消。 Runnable
已从调度程序的队列中删除,不管 的setRemoveOnCancelPolicy()
。
亲自尝试一下:
public class SchedulerTest {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
@Test
public void schedulerExecutionException() throws Exception {
log.info("Test: schedulerExecutionException");
ScheduledThreadPoolExecutor sched = new ScheduledThreadPoolExecutor(2);
sched.setRemoveOnCancelPolicy(true);
ScheduledFuture future1 = sched.scheduleAtFixedRate(new Runnable() {
int counter = 0;
@Override
public void run() {
log.info("Runnable 1: "+ ++counter);
if (counter >= 2) {
log.info("Runnable 1: BOOOM");
throw new RuntimeException("boom");
}
}
}, 1, 1, TimeUnit.SECONDS);
ScheduledFuture future2 = sched.scheduleAtFixedRate(new Runnable() {
int counter = 0;
@Override
public void run() {
log.info("Runnable 2: "+ ++counter);
}
}, 1, 1, TimeUnit.SECONDS);
long cutoff = new Date().getTime() + 6000;
while (new Date().getTime() < cutoff) {
log.info("Scheduler Queue size: "+ sched.getQueue().size());
log.info("Future 1: is "+ (future1.isCancelled() ? "" : "not ") +"cancelled, is "+ (future1.isDone()? "" : "not ") +"done");
log.info("Future 2: is "+ (future2.isCancelled() ? "" : "not ") +"cancelled, is "+ (future2.isDone()? "" : "not ") +"done");
Thread.sleep(1000);
}
assertEquals(sched.getQueue().size(), 1);
future2.cancel(true);
log.info("Scheduler Queue size: "+ sched.getQueue().size());
log.info("Future 1: is "+ (future1.isCancelled() ? "" : "not ") +"cancelled, is "+ (future1.isDone()? "" : "not ") +"done");
log.info("Future 2: is "+ (future2.isCancelled() ? "" : "not ") +"cancelled, is "+ (future2.isDone()? "" : "not ") +"done");
assertEquals(sched.getQueue().size(), 0);
sched.shutdownNow();
}
}