一定時間後に処理を行うには(Timer編)

◆PROCESSING 逆引きリファレンス

 カテゴリー:制御系

一定時間後に処理を行うには(Timer編)

【概要】

以前、PROCESSINGで一定時間後に処理を行う方法(一定時間後に処理を行うには)を紹介させてもらいました。

該当記事の中でマルチスレッドを使った時間計測について紹介をさせてもらいましたが、より汎用的なTimerクラスを使った方法もあるので、追加で紹介させてもらいたいと思います。

Timerクラスを使う方法もマルチスレッドを用いる方法の1つになりますが、thread()命令でマルチスレッドを行うよりも、簡単に呼び出せるので便利です。

Javaで利用可能なTimerには、java.util.Timer、javax.swing.Timer、javax.management.timer.Timer がありますが、ここではシンプルなjava.util.Timerを紹介します。

Timerクラスを利用すると

  • 一定時間後に、1回だけ別処理を呼び出す
  • 一定時間後から、定期的に繰り返し別処理を呼び出す

といった処理が簡単に実現できます。

なお欠点としては、「別処理」の中から直接画面への描画を行ってはいけない事でしょうか。この辺りは、前回記事のマルチスレッドを用いた時間計測でも同じことが言えます。

 

【詳細】

別処理部分を作成する

Timerにより呼び出される別処理部分を作成します。別処理部分は無名関数にしても良いですし、別クラスにしても良いでしょう。

どちらの場合もTimerTaskクラスを利用し、run()メソッドに別処理として動作する部分を記述します。

無名関数として実装する例:

別クラスとして実装する例:

こんな感じになります。

 

別処理部分を呼び出す

TimerTaskクラスの別処理を呼び出すには、JavaのTimerクラスを利用します。
.

Timerインスタンスを生成Timer timer = new Timer();
Timer timer = new Timer(String name);

timer:生成されたTimerインスタンス
name:生成するタイマー名

Timerインスタンスの作成は簡単ですね。

生成したTimerインスタンスを利用して、TimerTaskクラスを継承した別処理部分を呼び出します。別処理部分は、別スレッドで動作します。ですので別処理部分から直接画面へ描画を行うことはできない事に注意してください。

Timerクラスには、別処理部分を呼び出すための命令が2種類存在します。

  • scheduleメソッド
  • scheduleAtFixedRateメソッド

この2つの命令は、別処理部分が期待した時間内に処理を終えられなかったときに、動作が異なってきます。

scheduleメソッドの基本的な使い方

別処理を呼び出し1void timer.schedule( TimerTask task, Date firstTime);
void timer.schedule( TimerTask task, long delay, long period);
void timer.schedule(TimerTask task, Date firstTime, long period);

timer:生成されたTimerインスタンス
task:TimerTaskクラスを継承した別処理
firstTime:別処理を呼び出す日時
delay:別処理を呼び出すまでの待ち時間(ms)
period:別処理を呼び出す間隔(ms)

指定日時になったら1回だけ呼び出すには、例えば以下のようにします。

上記例では文字列を日付型に変換し、指定日時になったら呼び出しを行っています。

もしもscheduleメソッドを実行した時間が指定日時に比べて過去になっている場合(例:15:00に別処理を起動するように指定したが、その時点で既に16:00だった場合など)は、直ちに呼び出しが行われます。

ただしこの方法では、呼び出しは1回しか行われない事に注意してください。

一定間隔で繰り返し呼び出すには、以下のようにします。

上記例では、scheduleメソッドを実行した1秒後(1000ミリセカンド後)から5秒(5000ミリセカンド)間隔で、繰り返し別処理を呼び出します。

繰り返し呼び出す場合、もしも別処理側が指定時間(上記例なら5秒)以内に終わらなかった場合は、以下のようになります。

scheduleメソッドでは、1回でも処理遅延があると、その時間がどんどんと蓄積していく事になります。

ただし別処理側に遅延がなければ毎回periodミリ秒間隔で呼び出されるので、できるだけ一定間隔で処理を行いたい場合は、適した方法となります。

scheduleAtFixedRateメソッドの基本的な使い方

別処理を呼び出し1void timer.scheduleAtFixedRate(TimerTask task, Date firstTime, long period);
void timerscheduleAtFixedRate(TimerTask task, long delay, long period);

timer:生成されたTimerインスタンス
task:TimerTaskクラスを継承した別処理
firstTime:別処理を呼び出す日時
delay:別処理を呼び出すまでの待ち時間(ms)
period:別処理を呼び出す間隔(ms)

基本的な使い方はscheduleメソッドと同じです。

指定日時になったら呼び出すには、例えば以下のようにします。

上記例では文字列を日付型に変換し、指定日時になったら呼び出しを行っています。

もしもscheduleAtFixedRateメソッドを実行した時間が指定日時に比べて過去になっている場合(例:15:00に別処理を起動するように指定したが、その時点で既に16:00だった場合など)は、直ちに呼び出しが行われます。

scheduleメソッドと異なるのは、以降はperiodミリ秒間隔で(上記例では5000ミリ秒間隔で)、別処理が繰り返し呼び出される事です。

最初から一定間隔で繰り返し呼び出す場合には、以下のようにします。

上記例では、scheduleAtFixedRateメソッドを実行した直後(0ミリセカンド後)から5秒(5000ミリセカンド)間隔で、繰り返し別処理を呼び出します。

もしも別処理側が指定時間(上記例なら5秒)以内に終わらなかった場合は、以下のようになります。

scheduleAtFixedRateでは、可能な限り予定通りに呼び出そうとします。つまり一定時間の範囲内で、すべての呼び出しを終えたい場合に有効です。

逆に言えば別処理側に遅延が多い場合は、呼び出し間隔がバラバラになるので、そこは注意してください。

参考とした記事:
@IT様 : Javaのタスクを定期的に実行する

 

呼び出しを止める

繰り返し呼び出すのを停止するには、Timerクラスのcancelメソッドを利用します。
.

呼び出しの停止void timer.cancel();

timer:生成されたTimerインスタンス

使い方は簡単ですね。

cancelメソッドは、現在稼働中の別処理には影響を与えません。つまり実行中の別処理が即座に停止するわけではないという事です。

cancelメソッドが実行されると、次回から別処理が呼び出されることが無くなります。

なお、一旦キャンセルされたタイマーを再開する手段はありません。再開したい場合は、新しくscheduleまたはscheduleAtFixedRateメソッドを呼び出す必要があります。

【関連記事】

 


サンプルプログラム

一定時間後に繰り返し処理を行う例:

実行すると5秒間隔でOtherRunクラスのrunメソッドを呼び出します。マウスクリックで、呼び出しを停止します。

<出力サンプル>

 

一定時間経過した事を検出する例:

マウスをクリックすると、その時点から3秒経過したかどうかを計測し、メッセージを表示します。

<出力サンプル>


PROCESSING逆引きリファレンス一覧 へ戻る

本ページで利用しているアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。