java - 阻塞队列元素对其他线程不可见,有时会导致无法检索元素

标签 java multithreading queue blocking

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

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

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

问题出在我的环境中,有时第二个线程为空,尽管我可以看到第一个线程在 put 处阻塞调用(因为我已将队列大小初始化为 1)。此问题并不总是发生,只是有时会重复出现。无法理解导致此问题的原因,根据 java 文档,此队列似乎是线程安全的。有人可以就此分享任何观点吗?

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

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显示为空。

最佳答案

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

您需要一个操作来告诉当前线程“在此等待,直到队列中出现一个元素”。查看 API,peek() 的内容为

Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.

如果队列为空则返回null说明不执行等待。您要查找的操作是 take()

public E take()

Retrieves and removes the head of this queue, waiting if necessary until an element becomes available.

您在这里的用法将是:

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

关于java - 阻塞队列元素对其他线程不可见,有时会导致无法检索元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57092963/

相关文章:

java - response.sendRedirect 与 getRequestDispatcher

java - ImageJ 打开 imagePlus 窗口作为桌面 Pane 内的内部框架

java - 如何在 java 中为 jexcelapi 设置类路径

multithreading - 延迟处理更多请求/秒

c++ - Dijkstra 的 - 队列

java - 使用队列伪代码实现堆栈

java - 如何在不更改外观的情况下为多个 JProgressBar 独立设置 JProgressBar 文本颜色

c# - 为什么具有ContinueWith选项的第二个线程不等待第一个线程的结束?

python-3.x - 多线程异步s3调用增加了内存python

java - 比较链表中的元素