阻塞队列元素对其他线程不可见,有时导致没有元素检索

时间:2019-07-18 10:58:28

标签: java multithreading queue blocking

我正在使用LinkedBlokingQueue,它在2个线程之间共享。从第一线程构造函数中,我已经将Queue对象传递给第二线程。

我在第一个线程中使用likedBlockingQueue.put

第二个线程使用likedBlockingQueue.size()>0likedBlockingQueue.peek()来获取元素。

问题出在我的环境1中,有时第二个线程为空,尽管我可以看到第一个线程在放置调用时处于阻塞状态(因为我将队列大小初始化为1)。此问题并非总是发生,而有时只是复制。根据Java文档,此Queue似乎是线程安全的,因此无法理解是什么导致了此问题。有人可以分享任何观点吗?

我尝试复制它,但是只发生了几次,其他时候我可以从队列中获取元素。

1个线程

private final Queue<T> linkedQ = new LinkedBlokingQueue(1);
linkedQ.put(element);

2个线程

while(condition)
{
    if(this.linkedQ.size>0)
    {
        Object a = this.linkedQ.peek();
        linkedQ.remove();
        break;
    }
}

没有错误,当我调试此问题时,第二个线程中的Q显示为空。

1 个答案:

答案 0 :(得分:0)

在这种情况下,您既不应使用size()也不使用peek()remove()LinkedBlockingQueue是一个阻塞的队列(因此​​得名)。 size()peek()都是非阻塞的(嗯,从技术上讲,它们阻塞了一秒钟,但是它们并不是以生产者-消费者的方式起作用)。

您想要一个告诉当前线程“在这里等待,直到元素出现在队列中”的操作。查看该API,对于peek()来说,它显示为

  

检索但不删除此队列的头,如果此队列为空,则返回null。

如果队列为空,则返回null表示没有等待。您要查找的操作是take()

  

公开E take()

     

检索并删除此队列的头,如有必要,请等待直到元素可用。

您在这里的用法将是:

while(condition) {
    Object a = linkedQ.take(); // leaving out the interrupted exception for brevities sake
}