java多线程:如何知道使用者线程何时应从队列中删除元素

java多线程:如何知道使用者线程何时应从队列中删除元素,java,multithreading,producer-consumer,Java,Multithreading,Producer Consumer,我有一个生产者-消费者模型,arduino可以生成数据包,在我的电脑里我有一个java程序,它可以接收这些数据包并将它们放入阻塞队列。现在有线程处理这些数据包 假设X是生产者,A,B和C是消费者线程。有一个队列,所有使用者都可以引用它。消息(数据包)是不可变的对象(即消费者不能更改元素的状态)。我的问题是如何知道所有线程都是使用队列中的特定元素完成的,这样我就可以删除它? 以下是我的消费者run()方法: @Override public void run() { while (isSt

我有一个生产者-消费者模型,arduino可以生成数据包,在我的电脑里我有一个java程序,它可以接收这些数据包并将它们放入
阻塞队列
。现在有线程处理这些数据包

假设
X
是生产者,
A
B
C
是消费者线程。有一个队列,所有使用者都可以引用它。消息(数据包)是不可变的对象(即消费者不能更改元素的状态)。我的问题是如何知道所有线程都是使用队列中的特定元素完成的,这样我就可以删除它?

以下是我的消费者
run()
方法:

@Override
public void run()
{
    while (isStarted && !queue.isEmpty()) {
            updateMap(queue.peek());
    }
}
我考虑的一种设计是使用
有界的
队列。当生产者发现队列已满时,它将删除第一个元素。但我不确定这是否安全。我阅读了教程和更多内容,我得到的是:

若队列或存储桶已满,生产者应等待,若队列或存储桶已满,消费者应等待 水桶是空的

如果这听起来很明显,我很抱歉,但我对多线程编程是新手,代码的并发性对我来说很可怕

编辑:

所有
A
B
C
都是独立的。一个用于统计,一个用于更新网络地图等

编辑2:

正如@Augusto所建议的,还有另一种方法,
A
B
C
中的每一个都有自己的队列。我的网络侦听器将数据包传递给每个队列,并对其进行处理。它可以工作,但是如何仅使用一个队列执行此操作?是否可以仅使用一个队列执行此方案?如果答案是肯定的我需要如何以及何时从队列中删除元素?

(编辑后对我的评论进行跟踪)我建议每个线程使用不同的队列。这实际上是一个众所周知的模式,叫做

摘自上面的链接:

发布-订阅通道的工作原理如下:它有一个输入通道 分为多个输出通道,每个用户一个。 将事件发布到通道中时,发布订阅 通道将消息的副本传递到每个输出通道。 每个输出通道只有一个订户,只允许 消费一次消息。这样,每个订阅者只获得 消息一次,已消费的副本将从其通道中消失


ConcurrentLinkedQueue
BlockingQueue
之间的主要区别在于,您可以对
BlockingQueue上的元素数量添加限制。如果生产者从网络读取数据的速度快于消费者处理数据的速度,这是很好的。如果使用无界队列,并且这种情况持续一段时间,那么最终会出现
OutOfMemoryError

A
B
C
三者是否都需要按顺序处理数据包?如果是这种情况,您可以有3个队列:网络->
A
->
B
->
C
(其中箭头是不同的
ConcurrentLinkedQueue
)。如果顺序不重要,您可以在网络侦听器放置数据包的位置放置3个队列(因此
A
B
C
具有“专用队列”)@Augusto不,我放置了错误的消费者代码。我编辑了我的问题。所有
A
B
C
都独立运行。每个线程都有一个单独的队列好吗?如果我需要每个线程都有一个单独的队列,那么首先使用
BlockingQueue
有什么好处?我认为在事件驱动模型中,这种模式会很好,在这种模型中,不同的订阅者根据他们对特定事件的兴趣订阅频道。然而,在我的模型中,消费者总是在那里做某些事情。我不确定这是否是个好主意。在我看来,这似乎增加了不必要的复杂性。除了我最初的问题,一般来说,在一个负责在队列中创造更多空间的消费者/生产者中?因为即使使用
unbounded
queue,它也不是无限的,在某些情况下我们需要删除一些元素。因此,您的意思是我应该使用
ConcurrentLinkedQueue
然后每个线程执行其任务,然后当队列达到一定大小时,网络观察者必须删除第一个元素。是否正确?我的建议是使用一个有界的
阻塞队列
,当您调用
take()
(调用这个而不是
peek()
)时,元素将从队列中取出。谢谢。只有当我为每个线程使用单独的队列时,这才有效。关键是当我有不同的线程访问一个队列时,我不能调用
take()
,因为可能有另一个线程需要该元素。