初出 JAVA PRESS Vol.26

Java API ダイジェスト

java.util.Timer

Timerクラスは定期的に繰りかえす処理や、ある時刻になったら行う処理などをスケジュールするためのクラスです。例えば、アニメーションやタイマ割り込みなどに使用することができます。Timerクラスではこのような処理のことをタスクと呼び、TimerTaskクラスで表します。

Swingにも同名のクラスがありますが、こちらのタイマはGUIに特化しています。これに対して、java.utilのタイマはより汎用的に使用することができます。

Timerクラスは複数のタスクをスケジューリングすることができます。複数のタスクでも使用するスレッドは増加しないので、使用するスレッド数を抑えることができます。また、Timerクラスは同期化されているので、複数のスレッドから同一のタイマを使用することも可能です。


タスクのスケジューリング

Timerクラスのコンストラクタを紹介します。タイマが使用するスレッドの種類を指定することも可能です。

■ コンストラクタ

Timerクラスで定義されているのはタスクのスケジューリングとタイマのキャンセルです。

タスクのスケジューリングにはタスクと実行条件を指定して行います。

■ タスクのスケジューリング

cancelメソッドはスケジューリングされている全てのタスクをキャンセルし、タイマを終了させます。

■ タイマのキャンセル

タイマあれこれ

■ コンストラクタ

public Timer()
public Timer(boolean isDaemon)

Timerクラスのコンストラクタです。Timerオブジェクトが生成すると内部的にスレッドを1つだけ生成します。このスレッドを利用して複数のタスクをスケジュールします。

引数があるコンストラクタを使用すると、タイマが使用するスレッドをデーモンスレッドにするかどうかを指定できます。デーモンスレッドとは、実行中のスレッドがデーモンスレッドだけになると終了してしまうスレッドです。

■タスクのスケジューリング

public void schedule(TimerTask task, Date time)
public void schedule(TimerTask task, Date firstTime, long period)
public void schedule(TimerTask task, long delay)
public void schedule(TimerTask task, long delay, long period)

タスクをスケジュールするメソッドです。スケージュールするタスクはjava.util.TimerTaskクラスで表されます。TimerTaskクラスは抽象クラスで、その派生クラスはrunメソッドに行いたい処理を記述するようにします。

引数にDateクラスが使用されている場合は、Dateで表された時刻にタスクを処理します。delayが指定されている場合はscheduleメソッドをコールした時点よりdelayミリ秒後にタスクを処理します。

periodが指定されている場合は、タスクをperiodミリ秒ごとに繰り返し処理します。

タスクを一度だけ処理する目覚し時計をリスト1に示します。alarmTimeになったらタスクが処理され、ビープがなります。ここではタスクに無名クラスを使用しています。

あるGUIコンポーネントをperiodミリ秒ごとに再描画させるルーチンをリスト2に示します。リスト2はリスト1とは異なり、タスクをRepaintTaskというTimerTaskの派生クラスを使用して定義しています。

public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
public void scheduleAtFixedRate(TimerTask task, long delay, long period)

scheduleメソッドと同様にタスクをスケジューリングするためのメソッドですが、このメソッドはタスクを繰り返し行う場合だけ使用されます。

scheduleメソッドとのscheduleAtFixedRateの違いは、図1に示したように、繰り返し時間の設定が異なることです。schedule メソッドは繰り返し時間を実際にタスクが開始された時間から次のタスク開始時間を設定します。scheduleAtFixedRateメソッドはタスクが開始されるべき時間から次のタスクの開始時間を設定します。

したがって、scheduleメソッドは現在のタスク処理と次のタスク処理の間隔を重視し、GCなどの処理でタスクの処理が遅延したら、次の処理も遅延します。一方の、scheduleAtFixedRateメソッドはタスクの繰り返しに絶対的な時間が必要な場合に使用し、タスクが遅延しても、次の処理は遅延を取り戻して処理されます。

例えば、時計のように遅延しては困る場合にはscheduleAtFixedRateメソッドを使用します。リスト3は1秒ごとに時間を出力する例です。ここでscheduleメソッドを使用すると、遅延によってある秒数が抜けてしまうことがありますが、scheduleAtFixedRateメソッドではそれが回避できます。

■タイマーのキャンセル

public void cancel()

タイマーがスケジューリングしてあるすべてのタスクをキャンセルして、タイマーを終了させます。ただし、cancelメソッドをコールしたときに処理中のタスクはそのまま実行されます。

タイマーが終了するとタスクの再スケジューリングはできなくなります。

1つのタスクだけをキャンセルするにはキャンセルするタスクに対してTimerTask#cancelメソッドを使用します。

List 1 目覚し時計
    public void alarmSet(Timer timer, Date alarmTime) {
	TimerTask task = new TimerTask() {
	    public void run() {
        	java.awt.Toolkit.getDefaultToolkit().beep();
	    }
	};
	timer.schedule(task, alarmTime);
    }

 

List 2 繰り返し行うタスクの例
    public void repaintRepeatedly(Timer timer, Component comp, long period) {
        TimerTask task = new RepaintTask(Component comp); 
        timer.schedule(task, 0, period);
    }
 
    class RepaintTask extends TimerTask {
        private Component comp;
 
        public ReapintTask(Component comp) {
            this.comp = comp;
        }
 
        public void run() {
            comp.repaint();
        }
    }

 

List 3 時計
	Timer timer = new Timer();
	TimerTask task = new TimerTask() {
	    public void run() {
		System.out.println(new Date());
	    }
	};
	timer.scheduleAtFixedRate(task, 0, 1000);

 

schduleメソッドとscheduleAtFixedRateメソッドの相違点

図 1 schduleメソッドとscheduleAtFixedRateメソッドの相違点

(2002.09)