1タイマー – 基本


Timer



TimerTask

は、バックグラウンドスレッドでタスクをスケジュールするために使用されるjavaユーティリティクラスです。一言で言えば –



TimerTask


は実行するタスクでhttp://docs.oracle.com/javase/8/docs/api/java/util/Timer.html[

Timer

]はスケジューラ

です。


2タスクを1回スケジュールする


Timer

を利用して

単一のタスクを実行する

ことから始めましょう。

@Test
public void givenUsingTimer__whenSchedulingTaskOnce__thenCorrect() {
    TimerTask task = new TimerTask() {
        public void run() {
            System.out.println("Task performed on: " + new Date() + "n" +
              "Thread's name: " + Thread.currentThread().getName());
        }
    };
    Timer timer = new Timer("Timer");

    long delay = 1000L;
    timer.schedule(task, delay);
}

これがJUnitテストである場合は、

Thread.sleep(delay ** 2)

呼び出しを追加して、Junitテストの実行が停止する前にTimerのスレッドがタスクを実行できるようにする必要があります。


3間隔を空けて繰り返しタスクをスケジュールする

次に、

事前に定義された間隔で実行するようにタスクをスケジュールしましょう


scheduleAtFixedRate(repetitionTask、delay、period)

APIを使用します。これは、指定された遅延の後から開始して、タスクを繰り返し固定レート実行するようにスケジュールします。後続の実行は、指定された期間で区切られた定期的な間隔で行われます。

@Test
public void givenUsingTimer__whenSchedulingRepeatedTask__thenCorrect(){
    TimerTask repeatedTask = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
        }
    };
    Timer timer = new Timer("Timer");

    long delay  = 1000L;
    long period = 1000L;
    timer.scheduleAtFixedRate(repeatedTask, delay, period);
}

実行が何らかの理由(ガベージコレクションやその他のバックグラウンドアクティビティなど)で遅延した場合、「追いつく」ために2回以上の実行が連続して行われます。


3.1. 毎日のタスクをスケジュールする

次に –

1日に1回タスクを実行しましょう

:

@Test
public void givenUsingTimer__whenSchedulingDailyTask__thenCorrect() {
    TimerTask repeatedTask = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
        }
    };
    Timer timer = new Timer("Timer");

    long delay = 1000L;
    long period = 1000L **  60L **  60L **  24L;
    timer.scheduleAtFixedRate(repeatedTask, delay, period);
}


4

Timer



TimerTask


をキャンセル

タスクの実行は、いくつかの方法で取り消すことができます。


4.1.

run


内の

TimerTask

をキャンセルしてください


run()

メソッドの

TimerTask

自体の実装内で

TimerTask.cancel()

メソッドを呼び出すことによって、

@Test
public void givenUsingTimer__whenCancelingTimerTask__thenCorrect()
  throws InterruptedException {
    TimerTask task = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
            cancel();
        }
    };
    Timer timer = new Timer("Timer");

    timer.scheduleAtFixedRate(task, 1000L, 1000L);

    Thread.sleep(1000L **  2);
}


4.2.

Timer


をキャンセル


Timer

オブジェクトの

Timer.cancel()

メソッドを呼び出すことによって:

@Test
public void givenUsingTimer__whenCancelingTimer__thenCorrect()
  throws InterruptedException {
    TimerTask task = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
        }
    };
    Timer timer = new Timer("Timer");

    timer.scheduleAtFixedRate(task, 1000L, 1000L);

    Thread.sleep(1000L **  2);
    timer.cancel();
}


4.3.

run


内の

TimerTask

のスレッドを停止します.

タスクの

run

メソッド内でスレッドを停止して、タスク全体をキャンセルすることもできます。

@Test
public void givenUsingTimer__whenStoppingThread__thenTimerTaskIsCancelled()
  throws InterruptedException {
    TimerTask task = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
           //TODO: stop the thread here
        }
    };
    Timer timer = new Timer("Timer");

    timer.scheduleAtFixedRate(task, 1000L, 1000L);

    Thread.sleep(1000L **  2);
}


run

実装のTODO命令に注意してください。この簡単な例を実行するには、実際にスレッドを停止する必要があります。

実際のカスタムスレッド実装では、スレッドの停止をサポートする必要がありますが、この場合は非推奨を無視してThreadクラス自体に単純な

stop

APIを使用できます。


5

Timer

VS

ExecutorService


タイマーを使用する代わりに、ExecutorServiceを使用してタイマータスクをスケジュールすることもできます。

指定した間隔で繰り返しタスクを実行する方法の簡単な例を示します。

@Test
public void givenUsingExecutorService__whenSchedulingRepeatedTask__thenCorrect()
  throws InterruptedException {
    TimerTask repeatedTask = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
        }
    };
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    long delay  = 1000L;
    long period = 1000L;
    executor.scheduleAtFixedRate(repeatedTask, delay, period, TimeUnit.MILLISECONDS);
    Thread.sleep(delay + period **  3);
    executor.shutdown();
}

そのため、

Timer



ExecutorService

ソリューションの主な違いは何ですか?


  • Timer

    はシステムクロックの変化に敏感です。


ScheduledThreadPoolExecutor

は違います
**

Timer

には実行スレッドが1つだけあります。

ScheduledThreadPoolExecutor

任意の数のスレッドで構成できます
**

TimerTask

の内部でスローされるランタイム例外はスレッドを強制終了するので、

次のスケジュールされたタスクはそれ以上実行されません。

ScheduledThreadExecutor

を指定した場合 – 現在のタスクはキャンセルされますが、残りは実行され続けます


6. 結論

このチュートリアルでは、タスクを迅速にスケジュールするために、Javaに組み込まれているシンプルでありながら柔軟な

Timer

および

TimerTask

インフラストラクチャーを利用できる多くの方法を説明しました。必要に応じて、Javaの世界にはもちろん、はるかに複雑で完全なソリューション(http://quartz-scheduler.org/[Quartz library]など)がありますが、ここから始めるのがとても良いでしょう。

これらの例の実装はhttps://github.com/eugenp/tutorials/tree/master/core-java[the github project]にあります。これはEclipseベースのプロジェクトなので、インポートおよび実行が簡単ですそのまま。