web-dev-qa-db-ja.com

ScheduledExecutorServiceからタスクを削除する方法は?

scheduleAtFixedRate(Runnable, INIT_DELAY, ACTION_DELAY, TimeUnit.SECONDS);で定期的にいくつかの異なるタスクを実行するScheduledExecutorServiceがあります

また、このスケジューラで使用している別のRunnableもあります。スケジューラからタスクの1つを削除するときに問題が始まります。

これを行う方法はありますか?

異なるタスクに1つのスケジューラを使用して正しいことをしていますか?これを実装する最良の方法は何ですか?

55
thepoosh

scheduledAtFixedRate()によって返される未来を単にキャンセルします。

_// Create the scheduler
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
// Create the task to execute
Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
};
// Schedule the task such that it will be executed every second
ScheduledFuture<?> scheduledFuture =
    scheduledExecutorService.scheduleAtFixedRate(r, 1L, 1L, TimeUnit.SECONDS);
// Wait 5 seconds
Thread.sleep(5000L);
// Cancel the task
scheduledFuture.cancel(false);
_

もう1つ注意すべきことは、キャンセルしてもスケジューラからタスクが削除されないことです。 isDoneメソッドが常にtrueを返すことだけが保証されます。このようなタスクを追加し続けると、メモリリークが発生する可能性があります。例:クライアントのアクティビティまたはUIボタンのクリックに基づいてタスクを開始する場合、n回繰り返して終了します。そのボタンが何度もクリックされると、スケジューラにまだ参照があるため、ガベージコレクションできないスレッドの大きなプールになる可能性があります。

Java 7以降で利用可能なScheduledThreadPoolExecutorクラスでsetRemoveOnCancelPolicy(true)を使用することができます。後方互換性のために、デフォルトはfalseに設定されています。

86
JB Nizet

ScheduledExecutorServiceインスタンスがThreadPoolExecutorを拡張している場合(たとえばScheduledThreadPoolExecutor)、remove(Runnable)を使用できます(ただし、javadocの注意を参照してください。内部キューに配置される前に他のフォームに変換されたタスクを削除します。 ")またはpurge()

1
Gary