//////////////////// 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にセットするSource is here. (ZIP Format,1623Bytes,Shift-JIS)
* 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; } } } ////////////////////////////////////////////////////////////
常駐処理は、例えばHTTPサーバとか、MAILサーバのような、リクエストに応じて処理を行う、
いわゆるイベントドリブンとか呼ばれるものも分類されますし、
今回僕が作った、数秒のスリープをはさんで、同一の処理を延々と行うもので、
時間間隔起動とでもいうような処理も含まれると思います。
その時使用したのは、Threadを用いた「コテコテ」な処理で、
メインループを書いて、Thread.sleepをはさんでスリープさせ、
業務処理をそこに書いていくというものでしたが、
上記test1.javaの例をみれば分かるとおり、
Timer / TimerTaskを利用すれば、呼ぶ側も呼ばれる側も、すっきりした記述で済むことが分かります。
(もっとも、このクラスの存在に気づいたのは、終わった後でしたが。。。)
ちなみに、思いつきなんですが、test2.javaの方は、
UNIXのcronの真似事のようなことをしています。
毎分0秒の時に、タスクを実行するようになっています。
(結構まわりくどいことしてますが、もっとすっきり書けるかも知れません。)
常駐している処理を外部から止めるには?
とあるプロジェクトでは、外部ファイルに起動/停止の状態を書いておき、
それを随時監視するという方法で行っていましたが、
大量のI/Oが発生するし、あまり効率の良い方法とは言えませんね。
そこでまたまた思いつきなんですが、
タスクとは別のスレッドでSocketサーバをあるポートで立てておき、
そこに接続があった場合、タスクを止めるという方法であれば、
比較的リソースの消費は少ないと思います。
まあ、ポート番号の管理という別の問題が発生しますが。
というわけで、Javaで以下のような処理を記述する場合は、
Timer / TimerTaskの使用を検討してみてください。
◇時間起動(cronのようなもの)
◇時間間隔起動(監視処理のようなもの; 同じ処理を等間隔で実行)