0

在我的应用程序中,我有两个线程,分别是 ThreadA 和 ThreadB。ThreadA 是一个保存和操作一些数据的线程(生产者),而 ThreadB 是从 ThreadA 读取的相应消费者线程(只读)。
我想实现 ThreadB 通知 ThreadA 更新数据(这可能需要一些时间),并且当数据更改时,ThreadB 应该从 ThreadA 获取/请求它。只要 ThreadA 尚未完成数据更新,ThreadB 就不应等待,而是继续使用他拥有的当前(旧)数据进行工作。现在我的想法是使用观察者模式来通知 ThreadB ThreadA 已经完成更新

public class ThreadA implements Runnable {

private boolean sometimesTrue = false;
private int[] someBigArray = new int[XXX];


private synchronized int[] getBigArray() {
    return this.someBigArray;
}

private void fireListenerDataChanged() {
    for(ThreadAListener l : listeners) 
        l.notify();
}

private synchronized void updateArray() {
    //do some stuff on the array that takes a lot of time
}

@Override
public void run() {
    while(true) {
        if(sometimesTrue) {
            updateArray();
        }
    }
}


public void doUpdate() {
    this.sometimesTrue = true;
}

}


public class ThreadB implements Runnable, ThreadAListener  {

private int[] bigDataToWorkOn;
private Thread threadA;

public ThreadB(ThreadA threadA) {
    this.threadA = threadA;
}

@Override
public void run() {
        //do my stuff with bigDataToWorkOn 
        if(sometimesTrue) {
            threadA.doUpdate();
        }
}


public void notify() {
    this.bigDataToWorkOn = threadB.getBigArray();
}      

}

我的主要目标是避免使用某种 BlockingQueue,因为那时 afaik ThreadB 会等待他的工作,直到 ThreadA 传递队列中的数据。如果我在 ThreadB 的 while 循环中调用 getBigArray,也会出现同样的问题,因为当 ThreadA 当前在 updateArray 中工作时,ThreadA 将被锁定,而 ThreadB 也会等待 ThreadA 完成。那么这是一个正确的方法吗?

4

1 回答 1

0

这种方法可能是可行的解决方案,除了这个事实,如果你不想在你的方法中有无限循环,你必须sometimesTrue用修饰符标记字段。volatilerun()ThreadA

此外,如果您不希望自己ThreadA吃掉 100% 的单核,则必须在其run()方法内的循环中添加一些延迟:

public void run() {
    try {
        while(true) {
            if(sometimesTrue) {
               updateArray();
            }
            Thread.sleep(100);
        }
    } catch (InterruptedException e) {
      // ... do something with e 
    }
}
于 2013-06-07T13:31:40.977 回答