我有两个任务:第一个任务 (work
) 是重复发生的,第二个任务 (cleanup
) 是释放一些资源。 cleanup
任务应在重复出现的 work
任务完成后恰好运行一次,并且不会再次运行。
我的第一直觉是这样的:
ScheduledExecutorService service = ...;
ScheduledFuture<?> future = service.scheduleAtFixedRate(work, ...);
// other stuff happens
future.cancel(false);
cleanup.run();
这里的问题是 cancel()
立即返回。因此,如果 work
恰好正在运行,则 cleanup
将覆盖它。
理想情况下,我会使用像 Guava 的 Futures.addCallback(ListenableFuture future, FutureCallback callback)
这样的东西。 ( Guava 15 可能有 something like that )。
与此同时,当 future
被取消并且 work
不再运行时如何触发回调?
最佳答案
这是我提出的解决方案。它看起来很简单,但我仍然认为那里有更常见和/或更优雅的解决方案。我真的很想在像 Guava 这样的图书馆里看到一个......
首先我创建了一个包装器来对我的 Runnables 施加互斥:
private static final class SynchronizedRunnable implements Runnable {
private final Object monitor;
private final Runnable delegate;
private SynchronizedRunnable(Object monitor, Runnable delegate) {
this.monitor = monitor;
this.delegate = delegate;
}
@Override
public void run() {
synchronized (monitor) {
delegate.run();
}
}
}
然后我创建一个包装器以在成功调用 cancel
时触发我的回调:
private static final class FutureWithCancelCallback<V> extends ForwardingFuture.SimpleForwardingFuture<V> {
private final Runnable callback;
private FutureWithCancelCallback(Future<V> delegate, Runnable callback) {
super(delegate);
this.callback = callback;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean cancelled = super.cancel(mayInterruptIfRunning);
if (cancelled) {
callback.run();
}
return cancelled;
}
}
然后我用我自己的方法将它们整合在一起:
private Future<?> scheduleWithFixedDelayAndCallback(ScheduledExecutorService service, Runnable work, long initialDelay, long delay, TimeUnit unit, Runnable cleanup) {
Object monitor = new Object();
Runnable monitoredWork = new SynchronizedRunnable(monitor, work);
Runnable monitoredCleanup = new SynchronizedRunnable(monitor, cleanup);
Future<?> rawFuture = service.scheduleAtFixedRate(monitoredWork, initialDelay, delay, unit);
Future<?> wrappedFuture = new FutureWithCancelCallback(rawFuture, monitoredCleanup);
return wrappedFuture;
}
关于java - 周期性任务取消和完成时的回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15794792/