2016-11-11 26 views
2

私のプログラムはスレッドの配列をとり、main()から "Work"オブジェクトを取り出してスレッドクラスにプッシュする "Queue"クラスを含んでいます。どのように同じオブジェクトを共有するのを防ぐには?

class Queue { 
volatile boolean value = false; 
int i; 
Work[] WI; 
public Queue(int num) { 
    this.WI = new Work[num]; 
    this.i = 0; 
    } 
synchronized void enqueue(Work WI) { 
    if (value) { 
     try { 
      wait();} catch (Exception e) { 
      System.out.println(e); 
     } 
    } 
    this.WI[i++] = WI; 
    value = true; 
    notify(); 
} 
synchronized Work dequeue() { 
    if (!value) { 
     try { 
      wait();} catch (Exception e) { 
      System.out.println(e); 
     } 
    } 
    value = false; 
    notify(); 
    return this.WI[i - 1]; 
} 
} 

ここでは「ワーク」オブジェクトを取得して計算するスレッドクラスです。私が作ったものの

class Thread_Produce implements Runnable { 

Work WI; 
Queue q; 
int row, column,n,s, start; 
Thread t; 
public Thread_Produce(Queue q,int n) { 
    this.q = q; 
    t = new Thread(this); 
    this.n = n; 
    this.s = 0; 
    this.start = 0; 
    t.start(); 
} 

public void run() { 
     for (int j = 0; j < n; j++) { 
       this.WI = (Work) q.dequeue(); 
       for (int i = 0; i < WI.array1[0].length; i++) { 
        s = s + WI.array1[WI.row][i] * WI.array2[WI.column][i]; 
       } 
       System.out.println(s); 
       s = 0; 
      } 
} 

しかし、「キュー」クラスメソッドは、「キュー」からの私のスレッドアレイを共有し、同じ「仕事」オブジェクトを同期。 1つの配列は、前の配列を適切に実行することなくrunメソッドに入ります。私は何をすべきか?

答えて

1

いけない車輪の再発明、1を既存の使用:

使用ConcurrentLinkedQueueあなた自身の作成のあなたのキューinsteedとして。同期なしで100%スレッドセーフです。このような

+0

私はwait()とnotify()を使用して自分自身で処理したい – IAmBlake

+0

それにまともな理由はありますか、それとも学習目的のためですか? – Antoniossss

+0

学習目的のみ – IAmBlake

0

あなたのコード:

if (condition) 
    wait(); 

は動作しません。 waitメソッドはロックを解除し、呼び出しスレッドを待機状態にします。スレッドが待機状態から復帰すると、待機状態になる前にロックを取得する必要があります。しかし、その時点でどのスレッドが状態にあるのかは分かりません。通知を受け取っても、通知されたスレッドがすぐにロックを取得できるとは保証されず、他のスレッドが通知とロックの取得の間に動作している可能性があります。

代わりに、ループが発生したときに待機している状態を確認するために、常にループでwaitを呼び出すようにしてください。オラクルのチュートリアル、特にthe Guarded Blocks pageを参照してください。

また、通知を2つの別々のケースで使用しています。スレッドに通知されるとき、それは何か関連しているかもしれないし、そうでないかもしれない。代わりにnotifyallを使用してください。

フラグを使用する代わりに、配列に何かがあるかどうかを確認するだけです。

+0

あなたは(値)の代わりにif(value)を意味するのですか? – IAmBlake

+0

@IAmBlake:はい。ロックを再度取得すると、再度値を確認する必要があります。 –

関連する問題