web-dev-qa-db-ja.com

中断しない場合、Future.cancel()は何をしますか?

From Future.cancel()のJavaドキュメント

boolean cancel(boolean mayInterruptIfRunning)

このタスクの実行をキャンセルしようとします。タスクがすでに完了している場合、すでにキャンセルされている場合、またはその他の理由でキャンセルできなかった場合、この試行は失敗します。成功し、cancelが呼び出されたときにこのタスクが開始されていない場合、このタスクは実行されません。タスクがすでに開始されている場合、mayInterruptIfRunningパラメーターは、タスクを停止するために、このタスクを実行しているスレッドを中断する必要があるかどうかを決定します。

私の質問は、mayInterruptIfRunningがfalseの場合、キャンセルは何をするのですか?
タスクがすでに実行されている場合、タスクの実行をキャンセルまたは停止するにはどうすればよいですか?

19
Tom

中断していない場合は、キャンセルされた未来を通知するだけです。 isCancelled() で確認できますが、手動で確認しないと何も起こりません。

以下のサンプルコードは、その方法を示しています。

private static FutureTask<String> task = new FutureTask<String>(new Callable<String>() {

    @Override
    public String call() throws Exception {
        while (!task.isCancelled()) {
            System.out.println("Running...");
            Thread.sleep(1000);
        }
        return "The End";
    }

});

public static void main(String[] args) throws InterruptedException {
    new Thread(task).start();
    Thread.sleep(1500);
    task.cancel(false);
}

タスクが開始され、1.5回の反復後に停止するように指示されます。スリープを継続し(中断した場合はスリープしません)、その後終了します。

10
zapl

私の質問は、mayInterruptIfRunningがfalseの場合、キャンセルは何をするのですか?すでに実行されている場合、タスクの実行をキャンセルまたは停止するにはどうすればよいですか?

タスクがすでに実行を開始していて、mayInterruptIfRunningfalseの場合、何もする必要はありません。 Javaでは、スレッドを中断することが、完了前にスレッドを停止する唯一の安全な方法であると考えられています。それでも、実装固有の間隔で中断をチェックすることにより、タスクが「準拠」する必要があります。

関連: Javaでスレッドをどのように強制終了しますか?

3
Paul Bellora

タスクがすでに開始されていて、mayInterruptIfRunningがfalseの場合、何も実行されません。

以下はcancel()です

public boolean cancel(boolean mayInterruptIfRunning) {
    if (state != NEW)
        return false;
    if (mayInterruptIfRunning) {
        if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING))
            return false;
        Thread t = runner;
        if (t != null)
            t.interrupt();
        UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state
    }
    else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED))
        return false;
    finishCompletion();
    return true;
}

mayInterruptIfRunningがfalseの場合、cancel()は状態をNEWからCANCELEDに変更し、falseを返すだけで、他には何も実行されないことがわかります。

3
Slogen