任意のScheduledExecutorServiceに固定レートでスケジュールされたコマンドがある場合、キャンセルできるScheduledFutureも返します。 "cancel"は、キャンセルが返された後、コマンドがまだ実行されていないことを保証していません。ShceduledFutureをキャンセルして、runnableが中止されるのを待っていますか?
ほとんどの場合、十分な機能です。しかし、キャンセル後に現在のスレッドをブロックする必要があるときに、コマンドがすでに進行中であれば、私はusecaseを処理し、コマンドが完了するまで待つ。言い換えれば、キャンセルを呼び出したスレッドは、コマンドがまだ実行中であれば、先に進むべきではありません。 mayInterruptIfRunning = trueでキャンセルすることは適切ではありません。現在の実行を中断したくないため、通常の完了を待つだけです。
標準のJDKクラスでこの要件を達成する方法が見つかりませんでした。 質問1:私は間違っていましたが、この種の機能はありますか?
だから私はそれを単独で実装することにしました: import java.util.concurrent。*;
public class GracefullyStoppingScheduledFutureDecorator implements ScheduledFuture {
/**
* @return the scheduled future with method special implementation of "cancel" method,
* which in additional to standard implementation,
* provides strongly guarantee that command is not in the middle of progress when "cancel" returns
*/
public static ScheduledFuture schedule(Runnable command, long initialDelay, long period, TimeUnit unit, ScheduledExecutorService scheduler) {
CancellableCommand cancellableCommand = new CancellableCommand(command);
ScheduledFuture future = scheduler.scheduleAtFixedRate(cancellableCommand, initialDelay, period, unit);
return new GracefullyStoppingScheduledFutureDecorator(future, cancellableCommand);
}
private GracefullyStoppingScheduledFutureDecorator(ScheduledFuture targetFuture, CancellableCommand command) {
this.targetFuture = targetFuture;
this.runnable = command;
}
private final ScheduledFuture targetFuture;
private final CancellableCommand runnable;
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
runnable.cancel();
return targetFuture.cancel(mayInterruptIfRunning);
}
@Override
public long getDelay(TimeUnit unit) {
return targetFuture.getDelay(unit);
}
@Override
public int compareTo(Delayed o) {
return targetFuture.compareTo(o);
}
@Override
public boolean isCancelled() {
return targetFuture.isCancelled();
}
@Override
public boolean isDone() {
return targetFuture.isDone();
}
@Override
public Object get() throws InterruptedException, ExecutionException {
return targetFuture.get();
}
@Override
public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return targetFuture.get(timeout, unit);
}
private static class CancellableCommand implements Runnable {
private final Object monitor = new Object();
private final Runnable target;
private boolean cancelled = false;
private CancellableCommand(Runnable target) {
this.target = target;
}
public void cancel() {
synchronized (monitor) {
cancelled = true;
}
}
@Override
public void run() {
synchronized (monitor) {
if (!cancelled) {
target.run();
}
}
}
}
}
Question2:誰もが上記のコードのエラーを見つけることができますか?