これが私が思いついた解決策です。それはかなり単純に思えますが、もっと一般的でエレガントな解決策があると思います。グアバのような図書館で見たいです...
まず、ランナブルに相互排除を適用するラッパーを作成します。
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;
}