这是我想出的解决方案。这似乎很简单,但我仍然认为那里有更常见和/或优雅的解决方案。我真的很想在像番石榴这样的图书馆里看到一个……
首先,我创建一个包装器来对我的 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;
}