Javaタイマー
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ベースのプロジェクトなので、インポートおよび実行が簡単ですそのまま。