//////////////////// test1.java ////////////////////
// 一定時間置きに処理を行うサンプル
import java.util.Timer;
import java.util.TimerTask;
/**
* java.util.Timer / java.util.TimerTaskのサンプル
* @author taka
*/
public class test1
{
public static void main(String args[]) throws Exception
{
Timer timer = new Timer();
timer.schedule(new TestTimer(), 0, 1000);
}
/**
* 指定間隔置きに呼ばれる処理
* @author taka
*/
static class TestTimer extends TimerTask
{
public void run()
{
System.out.println("Hello, World!");
}
}
}
////////////////////////////////////////////////////////////
//////////////////// test2.java ////////////////////
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* java.util.Timer / java.util.TimerTaskのサンプル
* @author taka
*/
public class test2
{
public static void main(String args[]) throws Exception
{
new test2();
}
public test2() throws Exception
{
Timer timer = new Timer();
TestTimer task = new TestTimer();
// 初回スケジュール時間の算出
Date scheduledDate = addMinuteClearSecond(new Date());
while(true)
{
// スケジュール中はスキップ
if(!task.isRunning())
{
// 次回のスケジュールをセット
task = new TestTimer();
timer.schedule(task, scheduledDate);
// スケジュール中であることをセット
task.setRunning(true);
// 次回スケジュール時間をセット
scheduledDate = addMinuteClearSecond(scheduledDate);
}
Thread.sleep(500);
}
}
/**
* 1分足して秒を0にセットする
* ex) 14:30:24 → 14:31:00
* @param d Date
* @return 次の分の0秒
*/
private static Date addMinuteClearSecond(Date d)
{
Calendar cal = Calendar.getInstance();
cal.setTime(d);
// +1[min]
cal.add(Calendar.MINUTE, 1);
// 0[sec]
cal.set(Calendar.SECOND, 0);
return cal.getTime();
}
/**
* スケジュールされた時間に呼ばれる処理
* @author taka
*/
class TestTimer extends TimerTask
{
// スケジュールされているかどうかを表すフラグ
boolean isReady = false;
/**
* スケジュールされた時間に呼ばれる処理(本体)
*/
public void run()
{
System.out.println(new Date() + ": Hello, World!");
setRunning(false);
}
/**
* スケジュールされているかどうかをセットする
* @author taka
*/
public void setRunning(boolean isRunning)
{
this.isReady = isRunning;
}
/**
* スケジュールされているかどうかを返す
* @author taka
*/
public boolean isRunning()
{
return isReady;
}
}
}
////////////////////////////////////////////////////////////
Source is here. (ZIP Format,1623Bytes,Shift-JIS)
常駐処理は、例えばHTTPサーバとか、MAILサーバのような、リクエストに応じて処理を行う、
いわゆるイベントドリブンとか呼ばれるものも分類されますし、
今回僕が作った、数秒のスリープをはさんで、同一の処理を延々と行うもので、
時間間隔起動とでもいうような処理も含まれると思います。
その時使用したのは、Threadを用いた「コテコテ」な処理で、
メインループを書いて、Thread.sleepをはさんでスリープさせ、
業務処理をそこに書いていくというものでしたが、
上記test1.javaの例をみれば分かるとおり、
Timer / TimerTaskを利用すれば、呼ぶ側も呼ばれる側も、すっきりした記述で済むことが分かります。
(もっとも、このクラスの存在に気づいたのは、終わった後でしたが。。。)
ちなみに、思いつきなんですが、test2.javaの方は、
UNIXのcronの真似事のようなことをしています。
毎分0秒の時に、タスクを実行するようになっています。
(結構まわりくどいことしてますが、もっとすっきり書けるかも知れません。)
常駐している処理を外部から止めるには?
とあるプロジェクトでは、外部ファイルに起動/停止の状態を書いておき、
それを随時監視するという方法で行っていましたが、
大量のI/Oが発生するし、あまり効率の良い方法とは言えませんね。
そこでまたまた思いつきなんですが、
タスクとは別のスレッドでSocketサーバをあるポートで立てておき、
そこに接続があった場合、タスクを止めるという方法であれば、
比較的リソースの消費は少ないと思います。
まあ、ポート番号の管理という別の問題が発生しますが。
というわけで、Javaで以下のような処理を記述する場合は、
Timer / TimerTaskの使用を検討してみてください。
◇時間起動(cronのようなもの)
◇時間間隔起動(監視処理のようなもの; 同じ処理を等間隔で実行)