3

私はこれに対する満足のいく答えを見つけようとしています:

ScheduledFuture#cancel(false) が false を返す原因は何ですか? 基本的に、次のような新しいスケジューラを作成しています。

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
ScheduledFuture<?> schedulerStatus = scheduler.scheduleWithFixedDelay(this, 0L, 1L, TimeUnit.SECONDS);

run メソッド内には、次のようなものがあります。

public void run() {
    // Do some logic
    schedulerStatus.cancel(false);
}

私はJavaDocを見てきましたが、実際には何も役に立ちません。

「またはその他の理由でキャンセルできませんでした」

したがって、ここで正確に何が起こっているのかを理解するための助けは素晴らしいでしょう!

ありがとう

アップデート

上記の例をさらに拡張するには、次のようにします。

private final ScheduledExecutorService scheduler;
private volatile ScheduledFuture<?> schedulerStatus;

@Inject
public IndexChangeManagerImpl(IndexChangeMonitor monitor, IndexChangeObservable observable) {
    this.monitor = monitor;
    scheduler = Executors.newScheduledThreadPool(1);
}

@Override
public  void init() {
    if (schedulerStatus == null || schedulerStatus.isDone()) {
        // Kick of the scheduler to attempt to initiate the listener every second.
        schedulerStatus = scheduler.scheduleWithFixedDelay(this, 0L, 1L, TimeUnit.SECONDS);
    }
}

@Override
public void run() {
    try {
        // Before starting the monitor, ensure it is not currently running.
        monitor.shutdown();

        // Initiate the monitor.
        monitor.start();

        // Listener has been established, no more attempts necessary.
        schedulerStatus.cancel(false);

        lastLog = 0;
    } catch (ChangeMonitorException sfE) {
        long now = System.currentTimeMillis();

        if (lastLog == 0 || now - lastLog > 60000) {
            // Log every 60 seconds.
            DEBUG.error("Error attempting to initiate index change monitor.", sfE);
            lastLog = now;
        }
    }
}

うまくいけば、このコード スニペットは、cancel が false を返す 2 つの理由が実際には不可能であることを示しています (これはすべてシングル スレッドであることに注意してください)。単一のスケジュールされたスレッド内でキャンセルが呼び出されるため、明らかにタスクは完了しておらず、まだキャンセルされていません。

注意すべきことの 1 つは、false を返すキャンセルは断続的であり、システムに負荷がかかっているときに発生することです。

さらに考えはありますか?

4

1 に答える 1