web-dev-qa-db-ja.com

タスクを1回実行するようにスケジュールするにはどうすればよいですか?

一定時間後に「何かをする」カウントダウンタイマーの設定に沿って、何かを行うことを遅らせたい。

待機中にプログラムの残りの部分を実行し続けたいので、1分の遅延を含むThreadを自分で作成しようとしました。

public class Scratch {
    private static boolean outOfTime = false;

    public static void main(String[] args) {
        Thread countdown = new Thread() {
            @Override
            public void run() {
                try {
                    // wait a while
                    System.out.println("Starting one-minute countdown now...");
                    Thread.sleep(60 * 1000);

                    // do the thing
                    outOfTime = true;
                    System.out.println("Out of time!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        countdown.start();

        while (!outOfTime) {
            try {
                Thread.sleep(1000);
                System.out.println("do other stuff here");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


これは多かれ少なかれ機能しましたが、これを行うためのより良い方法があるはずです。

いくつかの検索の後、私はこれらのような質問をたくさん見つけましたが、彼らは私がやろうとしていることを実際には扱っていません:

これほど複雑なものは必要ありません。プログラムの残りの部分を実行したまま、一定の時間後に1つのことをしたいだけです。

「何かをする」ために1回限りのタスクをスケジュールするにはどうすればよいですか?

21
azurefrog

_Java.util.Timer_ は、将来のタスクをスケジュールするための良い方法でしたが、今では望ましいです1 代わりに_Java.util.concurrent_パッケージのクラスを使用します。

ScheduledExecutorService があります。これは、遅延後にコマンドを実行する(または定期的にコマンドを実行するように設計されていますが、この質問には関係ありません)。

schedule(Runnable, long, TimeUnit) メソッドがあります。

指定された遅延後に有効になるワンショットアクションを作成して実行します。


ScheduledExecutorServiceを使用すると、次のようにプログラムを書き直すことができます。

_import Java.util.concurrent.*;

public class Scratch {
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    public static void main(String[] args) {
        System.out.println("Starting one-minute countdown now...");
        ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                // do the thing
                System.out.println("Out of time!");
            }}, 1, TimeUnit.MINUTES);

        while (!countdown.isDone()) {
            try {
                Thread.sleep(1000);
                System.out.println("do other stuff here");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        scheduler.shutdown();
    }
}
_

この方法で行うことで得られる素晴らしいことの1つは、schedule()の呼び出しから返される_ScheduledFuture<?>_オブジェクトです。

これにより、余分なboolean変数を取り除き、ジョブが実行されたかどうかを直接確認できます。

cancel() メソッドを呼び出して、これ以上待機したくない場合は、スケジュールされたタスクをキャンセルすることもできます。


1Timerを優先してExecutorServiceを使用することを避ける理由については、 Java Timer vs ExecutorService? を参照してください。

26
azurefrog

それは私のために働いてくれてありがとう。スケジューラを使用して、実行時に計算されたバッチ間隔でタスクをスケジュールしました。

    manualTriggerBatchJob.setSchedulingProperties(pblId, batchInterval);
    ScheduledExecutorService scheduledExecutorService =
            Executors.newScheduledThreadPool(5);
    @SuppressWarnings("unchecked")
    ScheduledFuture scheduledFuture =
            scheduledExecutorService.schedule(manualTriggerBatchJob,
            batchIntervalInMin,TimeUnit.MILLISECONDS);
0
Apeksha Saxena