我遇到的问题就像单个生产者多个消费者问题。除了消费者是“不同的”,我需要一种“偷看”新项目(以检查它的用途)的方式。
问题实际上是一个服务于多个客户端线程的服务器线程。客户端将请求信息,然后服务器应回复此客户端
我该怎么做?可能性是一个循环:
while (true) {
if (q.peek() ... check here ...) {
// do something
} else {
Sleep(...); // prevent taking up too much CPU?
}
}
但似乎并不理想/对吗?
答案 0 :(得分:2)
以下是两个选项:
选项1.让队列中的一个消费者关闭项目并将其委托给“真正的”消费者。这个需要你做很多工作,因为你的主要消费者必须知道哪些“真正的”消费者忙碌。此外,如果其中一个“真实”消费者获得的资源多于其他消费者,则当主消费者等待传递消息时,它有可能阻止队列。
更好的解决方案是:
选项2.为每种类型的消费者使用一个队列。您的生产者将确定每种消息类型所属的队列,并将其放入正确的队列中。然后每个消费者都会从它感兴趣的队列中拉出来。
答案 1 :(得分:0)
您可能需要通过在单个块中同步它们来使以下操作成为原子。
// Make sure queue is final. If not, use a final Object monitor.
synchronized(queue) {
queue.peek
queue.pool
}
这是为了确保在您的消费者线程发现队列包含正确的目标消息(通过BlockingQueue.peek
)后,它可以使用该消息(通过BlockingQueue.pool
)
但是,您的解决方案并不理想。您正在实现名为busy pooling
的技术,这会浪费大量CPU资源。你没有利用BlockingQueue.pool
。 BlockingQueue.pool
将使您的消费者线程处于等待阶段,直到数据可用。
为了充分利用BlockingQueue.pool
,每个消费者线程都应该拥有自己的队列。这样他们就可以拨打pool
而无需执行忙peek
。
答案 2 :(得分:0)
也许最好不要使用BlockingQueue:
public class Synchronizer {
Object obj;
synchronized void put(Object obj) throws InterruptedException {
this.obj = obj;
notifyAll();
while(obj != null) {
wait();
}
}
synchronized Object take() throws InterruptedException {
for(;;) {
wait();
if (obj instanceof MyObject) {
notifyAll();
Object tmp = obj;
obj = null;
return tmp;
}
}
}
}
虽然可能有一个版本的Synchronzer消耗了BlockingQueue