Java 阻塞队列混乱
Java BlockingQueue confusion
我目前正在阅读有关 Java BlockingQueue 的文章,许多网站都提供了这个示例,用于简单实现 BlockingQueue。代码很简单,但我有点困惑。例如,假设我们填满了队列,然后我们尝试再入队 3 次。这将使 3 个线程等待。那么当我们调用dequeue时,dequeue方法中的代码会进入第二个if语句,它会通知所有线程。这不就意味着等待的3个线程都会往队列中添加节点吗?这意味着我们将比限制多 2 个节点?我很确定我在这里误解了一些东西,所以我可以使用一些小的解释。
public class BlockingQueue {
private List queue = new LinkedList();
private int limit = 10;
public BlockingQueue(int limit){
this.limit = limit;
}
public synchronized void enqueue(Object item)
throws InterruptedException {
while(this.queue.size() == this.limit) {
wait();
}
this.queue.add(item);
if(this.queue.size() == 1) {
notifyAll();
}
}
public synchronized Object dequeue()
throws InterruptedException{
while(this.queue.size() == 0){
wait();
}
if(this.queue.size() == this.limit){
notifyAll();
}
return this.queue.remove(0);
}
}
没有,只有一个会加一个节点。请注意,您在 enqueue
中的 wait
调用在一个循环中:
while(this.queue.size() == this.limit) {
wait();
}
所有三个线程都会收到通知,但 synchronized
块中只能有一个线程。第一个进入块的线程添加了一个节点,所以队列又满了。其他两个线程进入块(一个接一个),但看到队列再次满,这将使它们再次进入等待状态,因为那是 loop-condition.
您可以将 wait
想象成 synchronized
块的出口和入口点。当一个线程进入wait
,那么相应的锁就会被释放。一直在 wait
中等待并收到通知的线程正在尝试再次获取临界区的相应锁,如果当前正在使用则阻塞。所以通知的三个线程中一次只能有一个进入。
请注意 .enqueue()
中的 wait()
在循环内。任何被唤醒的线程都将 re-check 允许添加一个元素,并且由于一次只有一个线程可以执行同步方法,所以不会有问题 - 一个线程幸运地插入一个元素,其他线程在失败后继续等待 re-check.
我目前正在阅读有关 Java BlockingQueue 的文章,许多网站都提供了这个示例,用于简单实现 BlockingQueue。代码很简单,但我有点困惑。例如,假设我们填满了队列,然后我们尝试再入队 3 次。这将使 3 个线程等待。那么当我们调用dequeue时,dequeue方法中的代码会进入第二个if语句,它会通知所有线程。这不就意味着等待的3个线程都会往队列中添加节点吗?这意味着我们将比限制多 2 个节点?我很确定我在这里误解了一些东西,所以我可以使用一些小的解释。
public class BlockingQueue {
private List queue = new LinkedList();
private int limit = 10;
public BlockingQueue(int limit){
this.limit = limit;
}
public synchronized void enqueue(Object item)
throws InterruptedException {
while(this.queue.size() == this.limit) {
wait();
}
this.queue.add(item);
if(this.queue.size() == 1) {
notifyAll();
}
}
public synchronized Object dequeue()
throws InterruptedException{
while(this.queue.size() == 0){
wait();
}
if(this.queue.size() == this.limit){
notifyAll();
}
return this.queue.remove(0);
}
}
没有,只有一个会加一个节点。请注意,您在 enqueue
中的 wait
调用在一个循环中:
while(this.queue.size() == this.limit) {
wait();
}
所有三个线程都会收到通知,但 synchronized
块中只能有一个线程。第一个进入块的线程添加了一个节点,所以队列又满了。其他两个线程进入块(一个接一个),但看到队列再次满,这将使它们再次进入等待状态,因为那是 loop-condition.
您可以将 wait
想象成 synchronized
块的出口和入口点。当一个线程进入wait
,那么相应的锁就会被释放。一直在 wait
中等待并收到通知的线程正在尝试再次获取临界区的相应锁,如果当前正在使用则阻塞。所以通知的三个线程中一次只能有一个进入。
请注意 .enqueue()
中的 wait()
在循环内。任何被唤醒的线程都将 re-check 允许添加一个元素,并且由于一次只有一个线程可以执行同步方法,所以不会有问题 - 一个线程幸运地插入一个元素,其他线程在失败后继续等待 re-check.