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

Java 阻塞队列元素对其他线程不可见,有时会导致无法检索任何元素,java,multithreading,queue,blocking,Java,Multithreading,Queue,Blocking,我使用的是LinkedBlokingQueue,它在两个线程之间共享。从第一个线程构造函数中,我已将队列对象传递给第二个线程 我使用类似BlockingQueue的。将放在第一个线程中 第二个线程使用likedBlockingQueue.size()>0和likedBlockingQueue.peek()获取元素 问题是在我的环境1中,有时第二个线程给出的是空的,尽管我可以看到第一个线程在put时阻塞调用(因为我已将队列大小初始化为1)。这个问题并不总是发生,只是有时会重复。根据java文档,无

我使用的是
LinkedBlokingQueue
,它在两个线程之间共享。从第一个线程构造函数中,我已将
队列
对象传递给第二个线程

我使用类似BlockingQueue的
。将
放在第一个线程中

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

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

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

1个线程

private final Queue<T> linkedQ = new LinkedBlokingQueue(1);
linkedQ.put(element);
while(condition)
{
    if(this.linkedQ.size>0)
    {
        Object a = this.linkedQ.peek();
        linkedQ.remove();
        break;
    }
}

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

在这种情况下,您应该既不使用
size()
也不使用
peek()
也不使用
remove()
。是一个阻塞的队列(因此而得名)。
size()

您需要一个操作,告诉当前线程“在这里等待,直到队列上出现一个元素”。查看API,对于
peek()

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

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

公共电子商务

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

您在这里的用法是:

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

在这种情况下,您既不能使用
size()
也不能使用
peek()
remove()
。是一个阻塞的队列(因此而得名)。
size()

您需要一个操作,告诉当前线程“在这里等待,直到队列上出现一个元素”。查看API,对于
peek()

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

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

公共电子商务

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

您在这里的用法是:

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

Hi jhon谢谢你的回复我明白了你的意思,但我的疑问是,在这种情况下,由于队列是线程安全的,每当其他线程将元素放入Q时,它总是会看到,大小将超过0,因此它将从Q中移除。这是我预期的,但不是这样发生的,这是我首先无法理解的,永远不要调用
size
方法。第一次调用
take()
时,队列很可能是空的,但线程将挂起,直到另一个线程
put()
s。线程通信正在进行(Puting线程唤醒taking线程)。但是根据java文档,size将返回Q中的元素,因此它没有任何问题,对吗?BlockingQueue的目的是让线程等待,直到队列中有一个元素。大多数情况下,队列将是空的<代码>所以它没有任何问题,对吗?
没有任何问题。如果要等待/阻止某个元素的存在,则无需担心队列的大小。根据你的例子,看起来你应该等待一个元素出现在队列中是的,我也尝试过同样的方法,但最初的问题是,从第二个线程有时无法获取元素,我已经进行了线程转储,在第一个线程中,对象被放入Q,但从第二个线程中,它从未检索到线程只是停留在take conditionHi jhon,谢谢你的回答,我明白了你的意思,但我的疑问是,在这种情况下,由于队列是线程安全的,所以每当另一个线程将元素放入Q时,它总是会看到,将得到大于0的大小,因此它将从Q中删除。这是我预期的,但不会像这样发生,这是我无法理解的。首先,您不应该调用
size
方法。第一次调用
take()
时,队列很可能是空的,但线程将挂起,直到另一个线程
put()
s。线程通信正在进行(Puting线程唤醒taking线程)。但是根据java文档,size将返回Q中的元素,因此它没有任何问题,对吗?BlockingQueue的目的是让线程等待,直到队列中有一个元素。大多数情况下,队列将是空的<代码>所以它没有任何问题,对吗?
没有任何问题。如果要等待/阻止某个元素的存在,则无需担心队列的大小。根据你的例子,看起来你应该等待一个元素出现在队列中是的,我也尝试过同样的方法,但最初的问题是,从第二个线程有时无法获取元素,我已经进行了线程转储,在第一个线程中,对象被放入Q,但从第二个线程中,它从未检索到线程,只是停留在take条件下