/* マルチスレッドプログラミング 3つの同じスレッドを起動し、以下のように計算結果を比較する。 1×1+2×2+3×3+・・・・・+10×10 比較は2回計算するごとに(計5回)行う。 比較結果が正しければ続行、正しくなければ停止。 (i = 1、i = 3、i = 5、i = 7、 i = 9のタイミングで全スレッドのnが正しいかを比較) 計算は1/10の確率でエラーを起こすようにした。 [考え方] まず共有資源というものを作る。この場合は整数型のN1とN2とN3とフラグ(チェックコード)。 そして最初にフラグを0にセットする。 それでスレッド3つを動作させ、一つのスレッドがi=1に最初に到達した場合(フラ グが0の時)、N1にnの値を入れ、フラグを1にセットし、待機する。 そしてもう一つスレッドがi=1に到達した場合(フラグが1の時)、N2にnの値を入 れ、フラグを1にセットし、待機する。 同じように3つめのスレッドがi=1に到達した場合(フラグが2の時)、N3にnの値を入 れ、N1〜N3の値を比較。フラグを0に戻す。そしてスレッド全部に待機解除命令を送る。 間違った値のスレッドは終了する。 次はi=3,i=5,...について同じことを処理していく。 */ import java.util.Random; /********************************************************************************/ /* */ /* 共有資源クラス */ /* */ /********************************************************************************/ class Buffer{ int ns[] = new int[10];//計算結果格納 String tnames[] = new String[10];//スレッド名格納 int check_code;//チェックコード int thread_num;//同時に動いてるスレッドの個数 public String bad_name;//悪いスレッド名記憶 int bad_no;//悪いスレッドNO Random rand = new Random();//乱数 //コンストラクタ public Buffer(){ check_code=0; thread_num=0; bad_name=""; } //スレッド個数をセット public void set_thread(int num){ thread_num = num; } //スレッド個数を受け取る public int get_thread_num(){ return thread_num; } //スレッド個数を増やす public void plus_thread(String name){ thread_num++; System.out.println("スレッド"+name+"が生成されました。"+thread_num+"個目。"); } //計算結果の比較 void compare(){ bad_no = 0; //スレッドが3つのとき if(thread_num == 3){ if(ns[1] == ns[2] && ns[2]== ns[3] && ns[3] == ns[1]){ System.out.println("3つとも正しいです。"); }else if(ns[1] == ns[2]){ bad_name = tnames[3]; bad_no = 3; System.out.println("3番目のスレッド"+tnames[3]+"が間違っています。"); }else if(ns[2] == ns[3]){ bad_name = tnames[1]; bad_no = 1; System.out.println("1番目のスレッド"+tnames[1]+"が間違っています。"); }else if(ns[3] == ns[1]){ bad_name = tnames[2]; bad_no = 2; System.out.println("2番目のスレッド"+tnames[2]+"が間違っています。"); }else{ System.out.println("みんなバラバラです。"); } } //スレッドが2つのとき else if(thread_num == 2){ if(ns[1] == ns[2]){ System.out.println("2つとも正しいです。"); }else{ System.out.println("2つのスレッドの結果が違います。"); } } check_code = 0; } //比較(正しい場合にtrueを返す) synchronized boolean check(int n,String tname){ switch(check_code){ //最初のスレッド case 0: ns[1] = n;//計算結果取得 tnames[1] = tname;//スレッド名取得 check_code = 1; System.out.println("最初のスレッド"+tname+"。待ち状態に入ります。"); //待つ try{wait();}catch(Exception e){e.printStackTrace();} break; //二番目のスレッド case 1: ns[2] = n; tnames[2] = tname;//スレッド名取得 if(thread_num == 3){ System.out.println("二番目のスレッド"+tname+"。待ち状態入ります。"); check_code = 2; //待つ try{wait();}catch(Exception e){e.printStackTrace();} } else if(thread_num == 2){ System.out.println("二番目のスレッド"+tname+"が到着しました。"); //比較 System.out.println("比較を行います。"); compare(); System.out.println("全スレッドの待ち状態解除命令。"); //待ち状態解除通知 notifyAll(); } break; //三番目のスレッド case 2: ns[3] = n; tnames[3] = tname;//スレッド名取得 System.out.println("三番目のスレッド"+tname+"が到着しました。"); //ここで比較を行う System.out.println("比較を行います。"); compare(); System.out.println("全スレッドの待ち状態解除命令。"); //待ち状態解除通知 notifyAll(); break; } if(bad_no == 0){ return true; }else{ return false; } } } /********************************************************************************/ /* */ /* 計算クラス */ /* */ /********************************************************************************/ public class Calculation extends Thread { Buffer buffer = null; //コンストラクタ public Calculation(Buffer buffer){ this.buffer = buffer; buffer.plus_thread(getName());//スレッド個数を増やす } public void run() { int i; int m,n; boolean check_flag;//比較用フラグ int thread_num;//スレッド個数記憶 m=n=0; for(i=0;i<=10;i++){ m = i*i; n += m; //ランダムで処理を狂わす(10回に1回) if(buffer.rand.nextInt(10) == 0){ n+=1000; } //比較条件 if(i==1 || i==3 || i==5 || i==7 || i==9){ //スレッド個数記憶 thread_num = buffer.get_thread_num(); System.out.println("スレッド"+getName()+"がチェック関数に入ります。i="+i+",n="+n); check_flag = buffer.check(n,getName()); //正しい場合 if(check_flag == true){ //続行 } //正しくない場合 else{ //スレッド個数を減らす buffer.set_thread(thread_num - 1); //正しくなかったスレッドを終了 if(getName().equals(buffer.bad_name)){ System.out.println("スレッド"+getName()+"を終了させました。"); break; } } } } System.out.println(getName()+"が終了。"); } //メインメソッド public static void main(String args[]) { //共有資源作成 Buffer buffer = new Buffer(); //スレッド三つ起動 Calculation t1 = new Calculation(buffer); Calculation t2 = new Calculation(buffer); Calculation t3 = new Calculation(buffer); t1.start(); t2.start(); t3.start(); } }