Java:使用BlockingQueue的生产者/消费者:使用消费者线程wait()直到另一个对象排队

时间:2011-03-09 21:04:17

标签: java multithreading producer-consumer blockingqueue

我最近遇到了一些与线程有关的问题。这是原始的,除了占用大量的cpu不断检查队列之外,它工作正常。这个想法是可以随便调用cuePoint,主线程继续运行。

import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;


public class PointConsumer implements Runnable {
    public static final int MAX_QUEUE_SIZE=500;

    BlockingQueue<Point> queue;

    public PointConsumer (){
        this.queue=new ArrayBlockingQueue<Point>(MAX_QUEUE_SIZE);
    }

     public void cuePoint(Point p){
        try{
            this.queue.add(p);
        }
        catch(java.lang.IllegalStateException i){}
    }
     public void doFirstPoint(){
        if(queue.size()!=0){
            Point p=queue.poll();
            //operation with p that will take a while
        }
    }

    public void run() {
        while(true){
                  doFirstPoint();
        }
    }

}

我试图通过在每次调用cue函数时添加notify()来修复cpu问题,并将doFirstPoint()重新处理为这样的事情:

public void doFirstPoint(){

    if(queue.size()!=0){
            //operation with p that will take a while
    }
    else{
        try{
            wait();
        }
        catch(InterruptedException ie){}
    }
}

但是,我发现notify()和wait()仅适用于同步函数。当我使doFirstPoint和cuePoint同步时,调用cuePoint的主线程将一直等待。

我有一些想法来解决这个问题,包括将线程作为一个对象并直接通知它,但我不确定这是否会导致比修复更多的问题,是非常糟糕的形式,还是仅仅是不行。我错过了这个问题的简单解决方案吗?

2 个答案:

答案 0 :(得分:11)

BlockingQueue的要点是您不必自己编写此代码。

只需调用take(),它将等待一个对象插入队列,或者使用poll但是超时,这样如果超时,它只会返回null

编辑:只是为了澄清答案 - 正如评论中所说 - 这不仅意味着您可以删除等待/通知代码;您也可以删除大小检查,因为队列会为您执行此操作。

答案 1 :(得分:3)

为了补充说的内容,重要的是要注意put()和add()之间的区别。如果你的队列已满,你尝试插入的点可能永远不会实际插入队列中,因为会抛出IllegalStateException,而put()会在必要时等待插入点。

add()状态的文档

  

如果可以,则将指定的元素添加到此队列   立刻,成功后返回真实,否则抛出一个   IllegalStateException异常。

while put states

  

将指定的元素添加到此队列,必要时等待   空间可用