Mik*_*iev 5 java concurrency scheduled-tasks java.util.concurrent
我正在使用ScheduledExecutorService并提交这样的任务:
future = scheduledExecutorService.schedule(myRunnableTask, delay, timeunit)
Run Code Online (Sandbox Code Playgroud)
但是,一定时间后可能会发生某个事件,这表明不再需要此任务。所以我需要取消此任务,而我正在使用
boolean cancelled = future.cancel(false) 线。
取消后,我必须根据提交的可运行对象是否实际运行来采取不同的操作。在这里,让我们首先进入Oracle文档并阅读cancelled标志的含义:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)
返回:如果无法取消任务(通常是因为它已经正常完成),则返回false;否则返回false。否则为真
这就是关于返回值的全部内容。似乎写此文本行的人false在这里不确定返回值,但我认为我可以接受。
现在,让我们集中讨论返回的情况true。这里有两种可能性:
我对这两种情况都可以,但是我想知道实际发生的一种并采取相应的措施。如果可运行对象正在处理中,那么我可以完成它的工作,我想等待它完成,然后做一件事。但是,如果它被取消并且根本不会运行,我想做另一件事。
您能推荐一种解决方法吗?我想念什么吗?
我最终为这个问题写了这样的东西。源代码和一些单元测试可以在https://github.com/nuzayats/cancellabletaskexecutor找到
public class CancellableTaskExecutor {
private final ScheduledExecutorService es;
private final Logger log;
/**
* For a unit test to replicate a particular timing
*/
private final Runnable hookBetweenCancels;
public CancellableTaskExecutor(ScheduledExecutorService es, Logger log) {
this(es, log, () -> {
// nop
});
}
// For unit tests
CancellableTaskExecutor(ScheduledExecutorService es, Logger log, Runnable hookBetweenCancels) {
this.es = es;
this.log = log;
this.hookBetweenCancels = hookBetweenCancels;
}
public Execution schedule(Runnable task, long delay, TimeUnit unit) {
CancellableRunnable runnable = new CancellableRunnable(task);
ScheduledFuture<?> future = es.schedule(runnable, delay, unit);
return new Execution(future, runnable);
}
public class Execution {
private final ScheduledFuture<?> future;
private final CancellableRunnable runnable;
private Execution(ScheduledFuture<?> future, CancellableRunnable runnable) {
this.future = future;
this.runnable = runnable;
}
/**
* @return true when the task has been successfully cancelled and it's guaranteed that
* the task won't get executed. otherwise false
*/
public boolean cancel() {
boolean cancelled = runnable.cancel();
hookBetweenCancels.run();
// the return value of this call is unreliable; see /sf/ask/3914601211/
future.cancel(false);
return cancelled;
}
}
private class CancellableRunnable implements Runnable {
private final AtomicBoolean cancelledOrStarted = new AtomicBoolean();
private final Runnable task;
private CancellableRunnable(Runnable task) {
this.task = task;
}
@Override
public void run() {
if (!cancelledOrStarted.compareAndSet(false, true)) {
return; // cancelled, forget about the task
}
try {
task.run();
} catch (Throwable e) {
log.log(Level.WARNING, "Uncaught Exception", e);
}
}
boolean cancel() {
return cancelledOrStarted.compareAndSet(false, true);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
155 次 |
| 最近记录: |