0

最近,我遇到了一些与线程相关的问题,该问题与需要积分的消费者有关。这是原始版本,除了占用大量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 的主线程将一直等待。

我有一些想法来解决这个问题,包括使线程成为对象并直接通知它,但我不确定这是否会导致比它修复的问题更多、形式非常糟糕或根本不起作用。我缺少这个问题的简单解决方案吗?

4

2 回答 2

11

关键BlockingQueue是您不必自己编写此代码。

只需调用take(),它将等待直到将对象插入队列,或者使用poll但有超时,以便它仅null在超时过去时返回。

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

于 2011-03-09T21:07:58.143 回答
3

只是为了补充已经说过的内容,重要的是要注意 put() 和 add() 之间的区别。如果您的队列已满,您尝试插入的点可能永远不会真正插入队列中,因为将抛出 IllegalStateException,而 put() 将等待(如有必要)插入该点。

add() 状态的文档

如果可以立即将指定元素添加到此队列中,则在成功时返回 true,否则抛出 IllegalStateException。

同时放置状态

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

于 2012-01-13T04:16:12.473 回答