Wed, June 21, 2006
{update:2007-05-28}
定期的に繰り返し実行するタイマーの自作(timertask)
java.util.Timerとjava.util.TimerTaskを使えば、 定期的に繰り返し使えるタイマーを実現できます。
しかし、これらのクラスを素直に使った場合、
プログラムの終了時点で、Timerクラスの cancel() メソッドを呼び出して
タイマーを明示的に終了させる必要があります。
一見終了時に必ずキャンセルを必ず呼ぶなどというのは、簡単なことのようですが、
以下のケースでは問題が生じます。
- タイマーをコードのあちこちで使用する必要があり、終了時に確実にキャンセルを呼ぶのを忘れそうになるケース
- プログラムが終了してもJavaVMは終了しないケース
ほとんどのケースでは、実際にはキャンセルしわすれても、 プログラムの終了と同時にJavaVMも終了するので問題ない(はず)のですが、 アプレットのように、アプレットは終了してもJavaVMが終了しない ケースでは、キャンセルしわすれたタイマーが残ってしまいます。
したがって、タイマーの繰り返し実行機能は使いたいが、 タイマーのキャンセルを呼びたくない(呼ばなくてもプログラムの終了と同時に タイマーもキャンセルされる)場合に役に立つ MyTimerクラスを書いたのでメモしておきます。
コード
java.util.Timerを使うが、タスクは繰り返し実行させず、一度だけ実行するようにスケジュールします。
このままだと、一度実行したら終わってしまうので、タスクの最後にサイド次のタスクをスケジュールします。
このようにして、一度だけ実行するタスクを繰り返すことによって、繰り返し実行を実現します。
import java.util.*;
public class MyTimer{
private long interval;
public MyTimer(){
this(1000*1);
}
public MyTimer(long inverval){
super();
this.interval=interval;
setupNextTimer();
}
private ArrayList list=new ArrayList();
public void addMyTimerListener(MyTimerListener l){
list.add(l);
}
public void removeMyTimerListener(MyTimerListener l){
list.remove(l);
}
private Timer timer;
private void setupNextTimer(){
if(timer!=null){ timer.cancel(); }
timer=new Timer();
timer.schedule(new MyTimerTask(),1000*1);
}
private boolean sideURA;
private class MyTimerTask extends TimerTask{
public void run(){
for(int i=0; i<list.size(); i++){
MyTimerListener l=(MyTimerListener)list.get(i);
l.callback();
}
setupNextTimer();
}
}
}
public interface MyTimerListener{
void callback();
}
Test.java Test.java
public class Test{
public static void main(String[] argv){
MyTimerListener l=new MyTimerListener(){
private int count;
public void callback(){
System.out.println("callback:"+count);
count++;
}
};
MyTimer timer=new MyTimer();
timer.addMyTimerListener(l);
}
}