當在任何ScheduledExecutorService以固定費率計劃的任何命令時,它返回可以取消的ScheduledFuture。 但是,「取消」並不能保證命令在取消返回後仍不能執行,例如因爲當調用「cancell」時命令已經處於執行的中間。如何取消ShceduledFuture並等待可運行停止,如果在取消的時刻正在運行可執行文件?
對於大多使用情況下,有足夠的功能。但是在取消之後需要阻止當前線程時,我已經處理了用例,如果命令已在進行中,並等待命令完成。換句話說,如果命令仍在執行,調用cancel的線程不應該繼續前進。用mayInterruptIfRunning = true取消也不合適,因爲我不想破壞當前執行,我只需要等待正常完成。
我沒有找到如何實現通過標準JDK類此要求。 問題1:我錯了,這種功能是否存在?
所以我決定自行實施它。 進口的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();
}
}
}
}
}
問題2:可能有人發現在上面的代碼中的錯誤?