我目前正在阅读关于Java的文章,在许多网站上都给出了这个示例,以实现BlockingQueue的简单实现。代码很简单,但我有点困惑。例如,假设我们填充了队列,然后再尝试加入3次队列。这将使3个线程等待。然后,当我们调用dequeue时,dequeue方法中的代码将输入第二个if语句,并通知所有线程。这不意味着等待的3个线程都会向队列中添加节点吗?这意味着我们将多出两个节点的限制?我很肯定我在这里误解了一些东西,所以我需要一些小小的解释。
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);
}
}发布于 2020-08-07 10:04:33
不,只有一个会添加一个节点。注意,wait-call in enqueue在一个循环中:
while(this.queue.size() == this.limit) {
wait();
}所有三个线程都会被通知,但是只有一个线程可以在synchronized-block中。进入块的第一个线程添加了一个节点,因此队列又满了。另两个线程(一个接一个地)进入块,但是看到队列又满了,这将使它们再次进入等待状态,因为这是循环条件。
您可以将wait想象为synchronized-block的出口和内聚点。当线程进入wait时,相应的锁就会被释放。在wait中等待并收到通知的线程正试图再次获取关键部分的相应锁,如果它目前正在使用,则会阻塞。因此,通知的三个线程中只有一个可以一次进入。
发布于 2020-08-07 10:05:45
请注意,来自wait()的.enqueue()在循环中。任何唤醒线程都将重新检查允许添加元素,而且由于一次只有单个线程可以执行同步方法,所以没有问题--一个线程很幸运地插入了一个元素,其他线程在失败的重新检查之后继续等待。
https://stackoverflow.com/questions/63299412
复制相似问题