EeBlog(テクニカルブログ)

第12 回 イベント処理

今回は、EeB内で話題となっていたタイマー処理を実現すべく、 イベント処理について考えようと思います。

イベントという言葉はGUIプログラムをしたことがある人はおなじみかもしれません。
しかし、JavaのWebシステム開発ではあまり聴かない言葉ではないでしょうか?

イベントとは「オブジェクトに特定の現象が発生した時に発する信号」です。
イベントを使った処理とは、「オブジェクトに特定の現象が発生した時に処理を行う」事です。

つまり、オブジェクトから何らかの報告を受け、それに応じて処理を行います。
ここだけを見れば、以前書かせていただいた スレッドのwaitメソッドを利用した待ち合わせ処理 に似ています。
しかし、スレッドのwaitメソッドは処理を待つのに対してイベント処理は 待ちません。動きながらイベントが発生すれば処理を行うのです。

今回は、頭で書いたようにタイマーを実装してみました。
スタートメソッドを実行すると一定の間隔でイベントを発生します。

以下はタイマークラスです。
後に使用サンプルがあります…。

public class Timer {

     private long   interval    = 1000;       // イベント発生間隔
    private Status status      = Status.OFF; // 状態
    private Object listener = null; // イベントオブジェクト
    private String methodName  = null;       // イベントメソッド
    private Thread eventThread = null;       // イベント発生スレッド

    //==================================================
     // メソッドの登録
    //==================================================
     public void setEventListener(Object listener, String methodName) {
         this.listener = listener;
         this.methodName = methodName;
     }

     //==================================================
     // イベント発生間隔
    //==================================================
     public long getInterval() {
         return interval;
     }
     public void setInterval(long interval) {
         this.interval = interval;
     }

     //==================================================
     // 状態
    //==================================================
     public Status getStatus() {
         return status;
     }

     //==================================================
     // タイマー開始
    //==================================================
     public void start() {

         // 状態をONにする
        status = Status.ON;

         // イベントを発生
        // (メインスレッドで実行することで確実に1回は実行する)
         if (methodName != null) {
             try {
                 Method method = listener.getClass()
                   .getMethod(methodName, new Class[0]);
                 method.invoke(listener, new Object[0]);
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }

         // スレッド定義
        eventThread = new Thread(){
             public void run() {
                 try {
                     // 状態がONの間、繰り返す
                    while (status.equals(Status.ON)) {

                         // 一定間隔待ち
                        synchronized (this) {
                             long eventTime = 
                               System.currentTimeMillis() + interval;

                             while (System.currentTimeMillis() < eventTime) {
                                     this.wait(eventTime - System.currentTimeMillis());
                             }
                         }

                         // 他スレッドからの変更を受ける
                        Thread.yield();

                         // イベント発生前にもう一度、状態をチェック
                        if (!status.equals(Status.ON)) {
                             break;
                         }

                         // イベント発生
                        if (methodName != null) {
                             try {
                                 Method method = listener.getClass()
                                   .getMethod(methodName, new Class[0]);
                                 method.invoke(listener, new Object[0]);
                             } catch (Exception e) {
                                 e.printStackTrace();
                             }
                         }
                     }
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
             }
         };

         // スレッドスタート
        eventThread.start();
     }

     //==================================================
     // タイマー停止
    //==================================================
     public void stop() {
         status = Status.OFF;

         // タイマースレッドが終わるまで待つ
        try {
             eventThread.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }

     //**************************************************
     // タイマーの状態
    //**************************************************
     public enum Status {
         ON,
         OFF
     }

 }

以下、使用サンプルです。

public class Test {

     //==================================================
     // メイン
    //==================================================
     public static void main(String[] args) {

         // タイマーオブジェクト生成
        Timer t = new Timer();

         // イベントメソッドを登録
        t.setEventListener(new Test(), "timer");

         // イベントの発生間隔を設定
        t.setInterval(2000);

         // タイマースタート
        System.out.println("Start");
         t.start();

         // 10秒待つ
        try {
             Thread.sleep(10000);
         } catch (InterruptedException e) {
         }

         // タイマー終了
        t.stop();
         System.out.println("End");
     }

     //==================================================
     // タイマーイベント
    //==================================================
     public static void timer() {
         System.out.println("イベント発生:"
                 + System.currentTimeMillis() + "ms");
     }
 }

肉の食べられるイベント歓迎中!!!