ウォンツテック

そでやまのーと

Observable, Observer

Observableクラスを継承したクラスが被監視対象(監視されるオブジェクト)
となり、Observerインタフェースを実装したクラスが監視者となる。

Observable継承クラスのインスタンスに変化があると、notifyObservers()
 メソッドを呼び出したときに、登録されている全てのOberverに通知され
updateメソッドが実行される。

ObservableインスタンスでsetChanged()メソッドを呼び出し、
明示的に変更したとする事が出来る。

サンプルコード

import java.io.*;
import java.util.*;

public class ObservSample implements Runnable {
    static ObservableHandle oh = new ObservableHandle();

    public static void main(String[] args) {
        ObservSample os = new ObservSample();
        Thread th1 = new Thread(os);
        Thread th2 = new Thread(os);
        Thread th3 = new Thread(os);
        Thread th4 = new Thread(os);

        th1.start();
        th2.start();
        th3.start();
        th4.start();

        //上記のスレッドが全て起動するまで適当な計算をさせて待機
        //これが無いと3つしかメッセージが出力されなかったりする
        int sum=0;
        for(int i=0;i<100000000;i++) {
            sum += i;
        }

        oh.sendMessage("notify observable");
    }

    public void run() {
        ObserverHandle observ = new ObserverHandle(oh);
        System.out.println(observ.getNextMessage());
    }
}

class ObservableHandle extends Observable {
    public void sendMessage(String str) {
        setChanged();
        notifyObservers(str);
    }
}

class ObserverHandle implements Observer {
    ObservableHandle oh = null;
    String string = null;

    public ObserverHandle(ObservableHandle oh) {
        this.oh = oh;
    }

    synchronized public void update(Observable o, Object arg) {
        this.string = (String)arg;
        notify();
    }

    synchronized public String getNextMessage() {
        oh.addObserver(this);
        while (string == null) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        oh.deleteObserver(this);

        String strcopy = string;
        string = null;
        return strcopy;
    }
}