@634

スレッドの実験 その7

Advertisement

スレッド間の通信

wait()とnotify()ってメソッドでデッドロックとか例外を回避することができる。
スレッドでwait()を実行すると、そのスレッドはどこかのスレッドがnotify()するまで待ち状態になる。

悪い例。
public class Test{
    public static void main(String args[]){
        Intstack ints = new Intstack();
        Pushthread put = new Pushthread(ints);
        Popthread pot = new Popthread(ints);

        put.start();
        pot.start();
    }
}

//スタックにデータをプッシュするスレッド
class Pushthread extends Thread{
    Intstack intStc;

    public Pushthread(Intstack s){
        intStc = s;
    }

    public void run(){
        for(int i = 0; i < 10; i++){
            intStc.push((int)(Math.random() * 1.0) + 1);
            System.out.println((i+1) + "回目のプッシュ");

            try{
                Thread.sleep((int)(Math.random()*100));
            }catch(InterruptedException e){}
        }
    }
}

//スタックからデータをポップするスレッド
class Popthread extends Thread{
    Intstack intStc;

    public Popthread(Intstack s){
        intStc = s;
    }

    public void run(){
        for(int i = 0; i < 10; i++){
            System.out.println(intStc.pop() + " : "
                                    + (i+1) + "回目のポップ");

            try{
                Thread.sleep((int)(Math.random()*100));
            }catch(InterruptedException e){}
        }
    }
}

//スタックを管理するクラス
class Intstack{
    private static int s[] = new int[10];
    private static int sp = 0;

    //データ格納:排他制御付き
    public synchronized void push(int i){
        s[sp] = i;
        sp++;
    }

    //データ取り出し:排他制御付き
    public synchronized int pop(){
        sp--;
        return s[sp];
    }
}
結果
1回目のプッシュ
1 : 1回目のポップ
2回目のプッシュ
1 : 2回目のポップ
java.lang.ArrayIndexOutOfBoundsException: -1
         at Intstack.pop(th.java:65)
         at Popthread.run(th.java:42)
java.lang.ArrayIndexOutOfBoundsException: -1
         at Intstack.push(th.java:58)
         at Pushthread.run(th.java:21)
例外発生。何も入ってない所からデータを取り出そうとしたからダメ。
この場合の例外は配列に負の数のインデックスでアクセスしたから発生した。

wait() notify()を使う

wait()とnotify()で回避。

wait()されたスレッドはキューに入って待ち状態になる。それからnotify()でキューから取り出されて実行可能状態になる。
wait()してnotify()を忘れるとずっと待ち状態となり、プログラムが停止することになる。注意。
public class Test{
    public static void main(String args[]){
        Intstack ints = new Intstack();
        Pushthread put = new Pushthread(ints);
        Popthread pot = new Popthread(ints);

        put.start();
        pot.start();
    }
}

class Pushthread extends Thread{
    Intstack intStc;

    public Pushthread(Intstack s){
        intStc = s;
    }

    public void run(){
        for(int i = 0; i < 10; i++){
            intStc.push((int)(Math.random() * 1.0) + 1);
            System.out.println((i+1) + "回目のプッシュ");

            try{
                Thread.sleep((int)(Math.random()*100));
            }catch(InterruptedException e){}
        }
    }
}


class Popthread extends Thread{
    Intstack intStc;

    public Popthread(Intstack s){
        intStc = s;
    }

    public void run(){
        for(int i = 0; i < 10; i++){
            System.out.println(intStc.pop() + " : "
                                       + (i+1) + "回目のポップ");

            try{
                Thread.sleep((int)(Math.random()*100));
            }catch(InterruptedException e){}
        }
    }
}


class Intstack{
    private static int s[] = new int[10];
    private static int sp = 0;

    //データ格納:排他制御付き
    public synchronized void push(int i){
        if(sp >= s.length){
            try{
                wait();  //popされるまで待ち
            }catch(InterruptedException e){}		
        }

        s[sp] = i;
        sp++;
        notify();  //wait()解除
    }

    //データ取り出し:排他制御付き
    public synchronized int pop(){
        if(sp <= 0){
            try{
                wait();  //pushされるまで待ち
            }catch(InterruptedException e){}
        }

        sp--;
        notify();  //wait()解除
        return s[sp];
    }
}
結果。
1回目のプッシュ
1 : 1回目のポップ
2回目のプッシュ
1 : 2回目のポップ
3回目のプッシュ
1 : 3回目のポップ
4回目のプッシュ
1 : 4回目のポップ
5回目のプッシュ
1 : 5回目のポップ
6回目のプッシュ
1 : 6回目のポップ
7回目のプッシュ
8回目のプッシュ
1 : 7回目のポップ
9回目のプッシュ
1 : 8回目のポップ
10回目のプッシュ
1 : 9回目のポップ
1 : 10回目のポップ
もっと複雑だとnotifyAll()とか使わないと、プログラムがずっと停止したままになっちゃう場合もあるから要注意。臨機応変に。

Advertisement

ショートカット

634
634ブログ
このカテゴリのトップページに戻る
Incubator(Pukiwiki)
634ラボ
   UIコレクションギャラリー
   ZO-3ジェネレーター

サイト検索


Y!ログール