2010-07-02 87 views
2

问题是:类C控制类B是否让B再次将A添加到queueOfA,但是我怎样才能确保当A通知C,并在B的queueOfA变空之前立即更新,因为B类运行速度非常快,可能会删除所有A,因此在C更新之前变为空queueOfA,这可能会导致C的run方法结束。java线程同步问题,如何实现可观察线程

请帮我一把!

class A extends Observable implements Runnable{ 
    //... 
    void run(){ 
    //... 
    if (goBackToTheQueueAgain == true){ 
     setChanged(); 
     notifyObservers();//notify C that to let B add itself back 
    } 
    //... 
} 

class B extends implements Runnable{ 
    Queue<A> queueOfA;// initialy, queueOfA contains several A's 
    //... 
    void run(){ 
     //... 
     A retrieved = queueOFA.remove(); 
     Thread aThread = new Thread(retrieved); 
     aThread.start(); 
     //... 
    } 
} 

class C implements Observer, Runnable { 
    B b; //initially class C contains an instance of B 
    //... 
    void update(Observable o, Object arg){ 
     if(o instanceof A){ 
     A a = (A) o; 
     b.queueOfA.add(a); 
     } 
    } 
    //... 
    void run(){ 
     //... 
     Thread bThread = new Thread(b); 
     bThread.start(); 
     while (b.queueOfA.isEmpty() == false){ 
      // if queueOfA is not empty loop for ever 
     } 
     //.. 
    } 
} 
+0

哇,这是一些句子!我想你说,呃,一口气! – mdma 2010-07-02 18:58:19

+0

深呼吸:) – 2010-07-02 19:01:51

+0

我有一个可怕的英语表达风格。 – Rn2dy 2010-07-02 19:24:27

回答

5

的问题不在于你必须尽快通知更新 - 你不能保证。例如,考虑你在队列中只有一个元素开始。这将从队列中移除,然后队列为空,但该元素仍在处理中。 A线程可以采取它喜欢的时间 - 即使队列为空,C也不应该终止。

修复方法是C应该等到所有A都完全处理完毕。也就是说,A的运行方法已经结束,而不会将A重新放回队列。这可以使用倒计时锁存器来完成。最初将锁存器设置为队列的大小(A的数量),并在每次A完全处理时减少该锁存器。只有当该锁存器变为零时C才会退出。

C相类似这样

CountdownLatch latch; 

void run(){ 
    //... 
    this.latch = new CountDownLatch(queueOfA.size()); 
    Thread bThread = new Thread(b); 
    bThread.start(); 
    latch.await(); 
    //.. catch InterruptedException etc.. 
} 

void notifyDone(A a) { 
    this.latch.countDown(); 
} 

和A的run方法是

void run(){ 
    //... 
    C c = ...; // passed in from somewhere 
    if (goBackToTheQueueAgain == true){ 
     setChanged(); 
     notifyObservers();//notify C that to let B add itself back 
    } 
    else 
     c.notifyDone(this); 
} 

A需要到C的引用,以便它可以直接在它完成通知。

就我个人而言,我不会在这里使用Observer/Observable,因为您的通知具有特定含义 - 该项目可以重新排序。观察者模式最适合通知状态的变化,状态可以从被观察的实例中获得。这不是这种情况,并且从这种抽象的解耦中没有真正的收益。如果你想保持抽象而不是将A耦合到C,你可以引入一个额外的接口,例如

interface QueueHandler<T> 
{ 
    void requeue(T t); 
    void completed(T t); 
} 

并在C上实现它,并将它传递给每个A而不是当前的Observer接口。但同样,A类和C类紧密耦合,所以你也可以将C传递给A并让它直接通知。

+0

闩锁的东西是好的,但问题仍然是B快速删除queueOfA中的所有元素,所以B快速完成,但锁存器从不倒计数到零,因为A不再通知C!所以我们真的需要让A完成更新然后让B执行remove然后... – Rn2dy 2010-07-02 21:55:43

+0

问题是:B最初设置为运行一个固定时间,在执行过程中如果B变空,则B将立即停止执行,但由于A有可能再次返回队列,所以A必须确保C让A在B发现自己是空的之前回到队列中! 请帮我一把。 Mr.mdma – Rn2dy 2010-07-02 22:08:54

+0

我不明白为什么A不通知C - 它是A的运行方法的一部分。你可以让B使用BlockingQueue.take(),直到一个元素可用 - B永远不会退出 - 循环是无条件的。当C发现锁存器为0时(在latch.await()之后)它可以中断B,使得B跳出循环。 – mdma 2010-07-02 22:16:22