java BlockingQueue没有阻塞偷看?
我有一个阻塞队列的对象。
我想写一个阻塞的线程,直到队列中有一个对象。 与BlockingQueue.take()提供的function类似。
但是,由于我不知道我是否能够成功处理对象,我想只是peek()而不是删除对象。 我想删除该对象只有我能够成功处理它。
所以,我想要一个阻塞的peek()函数。 目前,peek()只是在队列为空时根据javadoc返回。
我错过了什么吗? 有没有其他方法来实现此function?
编辑:
如果我只使用线程安全队列而偷看和睡觉的任何想法?
public void run() { while (!__exit) { while (__queue.size() != 0) { Object o = __queue.peek(); if (o != null) { if (consume(o) == true) { __queue.remove(); } else { Thread.sleep(10000); //need to backoff (60s) and try again } } } Thread.sleep(1000); //wait 1s for object on queue } }
请注意,我只有一个消费者线程和一个(单独的)生产者线程。 我想这不如使用BlockingQueue有效……任何评论都赞赏。
您可以使用LinkedBlockingDeque并从队列中物理删除该项(使用takeLast()
),但如果使用putLast(E e)
处理失败,则在队列末尾再次替换它。 同时你的“生产者”会使用putFirst(E e)
将元素添加到队列的前面 。
您始终可以在自己的Queue
实现中封装此行为,并提供一个blockingPeek()
方法,该方法在底层putLast()
的幕后执行takeLast()
后跟putLast()
。 因此,从调用客户端的角度来看,元素永远不会从队列中删除。
但是,由于我不知道我是否能够成功处理对象,我想只是peek()而不是删除对象。 我想删除该对象只有我能够成功处理它。
通常,它不是线程安全的。 如果,在peek()
并确定对象可以成功处理之后,但在take()
它移除并处理之前,另一个线程会获取该对象,该怎么办?
我唯一知道的是这是Apache Commons Collections中的 BlockingBuffer :
如果在空Buffer上调用get或remove,则调用线程将等待add或addAll操作已完成的通知。
get()
等效于peek()
,通过使用BlockingQueue
装饰UnboundedFifoBuffer ,可以使Buffer
像BlockingQueue
一样运行
您是否也可以将事件侦听器队列添加到阻塞队列中,然后在(阻塞)队列中添加某些内容时,将事件发送给侦听器? 你可以让你的线程阻塞,直到它的actionPerformed方法被调用。
快速的答案是,并不是没有一种方法可以阻止窥视,实现一个阻塞队列自己阻塞peek()。
我错过了什么吗?
peek()在并发方面很麻烦 –
- 如果你不能处理你的peek()’消息 – 它将被留在队列中,除非你有多个消费者。
- 如果您无法处理该对象,谁会将该对象排除在队列之外?
- 如果你有多个消费者,你会在你偷看()和另一个线程处理项目之间遇到竞争条件,导致重复处理或更糟。
听起来你可能会更好地删除项目并使用责任链模式处理它
编辑:re:你的最后一个例子:如果你只有一个消费者,你将永远不会删除队列中的对象 – 除非它在同一时间更新 – 在这种情况下你最好非常小心线程安全和可能不应该把项目放在队列中。
看起来像BlockingQueue本身没有您指定的function。
我可能会尝试稍微重新解决这个问题:对于无法“正确处理”的对象,您会怎么做? 如果您只是将它们留在队列中,则必须在某个时刻将它们拉出来并处理它们。 我建议要么弄清楚如何处理它们(通常,如果一个queue.get()给出任何类型的无效或坏的值,你可能只是把它放在地板上)或选择不同的数据结构。一个FIFO。
本身不是答案,但是: JDK-6653412声称这不是一个有效的用例。