2016-11-11 40 views
2

我的程序需要一個線程數組,它還包含一個由我定義的「隊列」類,它從main()中取得「Work」對象並將它們推入線程類。如何防止共享相同的對象?

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]; 
} 
} 

這是我的Thread類,它需要「Work」對象並進行計算。

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; 
      } 
} 

但是,儘管我做了「排隊」類方法從「隊列」同步我的線陣列股相同的「工作」對象。一個數組在沒有正確執行前一個數組的情況下進入run方法。我該怎麼辦?

回答

1

不要另起爐竈,利用現有的一個:

使用ConcurrentLinkedQueue爲創建自己的您的隊列insteed。它是100%線程安全的,沒有同步。

+0

但我想通過我自己使用wait()和notify() – IAmBlake

+0

是否有任何體面的原因,或者它只是爲了學習目的? – Antoniossss

+0

只能學習目的 – IAmBlake

0

你這樣的代碼:

if (condition) 
    wait(); 

不起作用。 wait方法釋放鎖並將調用線程置於等待狀態。一旦線程從等待中醒來,它必須先獲取鎖定,然後才能讓呼叫等待。但是此時線程並不知道狀態是什麼。接收通知並不能保證通知的線程可以立即獲取鎖,其他線程可能會在通知和獲取鎖之間採取行動。

反而總是在循環中調用等待,以便當線程喚醒時,它會檢查一旦它有鎖就等待的條件。請參閱Oracle教程,尤其是the Guarded Blocks page

此外,您正在使用通知兩個單獨的案件。當一個線程被通知時,它可能是相關的或可能不相關的。改用notifyall。

而不是使用一個標誌,只是檢查數組中是否有任何東西。

+0

你的意思,而(價值),而不是如果(價值)的一切都不要灰心? – IAmBlake

+0

@IAmBlake:是的。一旦你重新獲得鎖定,你需要再次檢查值。 –