我正在使用ScheduledExecutorService并提交类似的任务:
future = scheduledExecutorService.schedule(myRunnableTask, delay, timeunit)
但是,在无限期的时间之后可能会发生某个事件,这表示不再需要此任务。所以我需要取消这个任务,我正在使用
boolean cancelled = future.cancel(false)
线。
取消后,我必须采取不同的操作,具体取决于提交的runnable是否实际运行。在这里让我们首先跳转到Oracle文档并阅读cancelled
标志的含义:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)
返回:如果无法取消任务,则返回false,通常是因为它已经正常完成;否则为真
这就是关于回报价值的全部内容。好像写这篇文章的人不确定false
这里的返回值,但我想我可以接受它。
让我们现在关注案例,当它返回true
。这里有两种可能性:
我对这两种情况都很好,但我想知道哪一个实际发生并采取相应的行动。如果runnable正在进行中,那么我可以完成它的工作,我想等待它完成然后做一件事。但如果它被取消并且根本不会运行,我想做另一件事。
你能推荐一个方法吗?我错过了什么吗?
您可以通过以下方式实现目标:
Set<Runnable>
,它跟踪已经开始由线程池执行的Runnable
s。Map<ScheduledFuture<?>, Runnable>
映射到各自的ScheduledFuture<?>
的Runnable
。
在安排任务后,你应该立即将ScheduledFuture
及其各自的Runnable
添加到Map
。
如果这个插入Map
是通过调度任务本身原子地执行,那么你可以避免ScheduledFuture
从未被添加到Map
的边缘情况,即使它被取消。我建议将你的ScheduledExecutorService
改为ScheduledThreadPoolExecutor
,这将允许你覆盖它的beforeExecute(Thread, Runnable)
方法;在已经为池分配了将执行任务的线程之后,在池运行任务之前立即调用此方法。
覆盖此方法时,可以将Runnable
添加到Set<Runnable>
。
然后,当一个ScheduledFuture
被取消时,你可以调用set.contains(map.get(future))
,它告诉你是否执行了Runnable
(ScheduledFuture
映射到)。
请注意,您的Set<Runnable>
和Map<ScheduledFuture<?>, Runnable>
实现可能必须是线程安全的,以避免可能的竞争条件。