java BlockingQueue没有阻塞偷看?

rou*_*ble 31 java queue peek blockingqueue

我有一个阻塞队列的对象.

我想写一个阻塞的线程,直到队列中有一个对象.与BlockingQueue.take()提供的功能类似.

但是,由于我不知道我是否能够成功处理对象,我想只是peek()而不是删除对象.我想删除该对象只有我能够成功处理它.

所以,我想要一个阻塞的peek()函数.目前,peek()只是在队列为空时根据javadoc返回.

我错过了什么吗?还有其他方法可以实现此功能吗?

编辑:

如果我只是使用了一个线程安全队列并且偷看和睡觉了?

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
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我只有一个消费者线程和一个(单独的)生产者线程.我想这不如使用BlockingQueue有效......任何评论都赞赏.

Ada*_*ski 14

您可以使用LinkedBlockingDeque并从队列中物理删除该项(使用takeLast()),但如果处理失败,则在队列末尾再次替换它putLast(E e).与此同时,您的"生产者"将使用的元素添加到队列的前面putFirst(E e).

您总是可以在自己的Queue实现中封装此行为,并提供一个blockingPeek()方法,takeLast()然后putLast()在底层的幕后执行LinkedBlockingDeque.因此,从调用客户端的角度来看,元素永远不会从队列中删除.

  • 这是一个很好的建议.我在这里看到的唯一问题是,如果在处理项目时队列填满,那么我将无法将当前项目排队. (2认同)
  • 我建议不要删除和重新添加,因为那样你就有把队列的状态更改暴露给其他线程的麻烦.也许使用繁忙的轮询来实现peek().或者,如果您不想轮询,请使用绑定到包装器中队列的信号量. (2认同)

Pav*_*aev 6

但是,由于我不知道我是否能够成功处理对象,我想只是peek()而不是删除对象.我想删除该对象只有我能够成功处理它.

通常,它不是线程安全的.如果在您peek()确定对象可以成功处理之后,但在您take()删除和处理之前,另一个线程将获取该对象,该怎么办?