2016-11-11 41 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:是的。一旦你重新获得锁定,你需要再次检查值。 –