当前位置: 代码网 > 服务器>网站运营>运维 > 阻塞队列BlockingQueue是如何唤醒等待的线程的呢?

阻塞队列BlockingQueue是如何唤醒等待的线程的呢?

2024年08月02日 运维 我要评论
当队列状态改变时(例如,生产者添加了一个元素或消费者取出一个元素),相应的条件会被信号唤醒,这样等待的线程就可以重新获取锁并继续执行。这将导致消费者线程释放锁并等待,直到另一个线程(生产者)在队列中插入一个元素并调用。这个锁用于同步对队列的访问,确保在任何时刻只有一个线程可以修改队列。: 当生产者向队列中添加一个元素时,它会调用。方法来唤醒一个(或所有)等待的消费者线程。: 当队列为空时,消费者线程会调用条件。: 队列内部维护了一个锁,通常是。条件用于通知消费者队列非空,而。方法来唤醒等待的消费者线程。

在 java 中,concurrentlinkedqueuearrayblockingqueuelinkedblockingqueue 等并发队列通常用于生产者-消费者模式。这些队列使用锁和条件(condition)来实现线程间的通信。

以下是基于 arrayblockingqueue 或 linkedblockingqueue 的生产者-消费者模式中,消费者如何知道队列中有元素可用的基本原理:

  1. 锁(lock): 队列内部维护了一个锁,通常是 reentrantlock。这个锁用于同步对队列的访问,确保在任何时刻只有一个线程可以修改队列。

  2. 条件(condition): 锁关联了两个条件,通常称为 notempty 和 notfullnotempty 条件用于通知消费者队列非空,而 notfull 条件用于通知生产者队列未满。

  3. 消费者等待: 当队列为空时,消费者线程会调用条件 notempty 的 await() 方法。这将导致消费者线程释放锁并等待,直到另一个线程(生产者)在队列中插入一个元素并调用 signal() 或 signalall() 方法来唤醒等待的消费者线程。

  4. 生产者通知: 当生产者向队列中添加一个元素时,它会调用 notempty 条件的 signal() 方法来唤醒一个(或所有)等待的消费者线程。

以下是一个简化的例子:

import java.util.concurrent.locks.condition;
import java.util.concurrent.locks.lock;
import java.util.concurrent.locks.reentrantlock;

public class boundedbuffer {
    final lock lock = new reentrantlock();
    final condition notempty = lock.newcondition();
    final condition notfull = lock.newcondition();
    final object[] items = new object[100]; // 假设缓冲区大小为100
    int putptr, takeptr, count;

    public void put(object x) throws interruptedexception {
        lock.lock();
        try {
            while (count == items.length) // 如果队列已满,则等待
                notfull.await();
            items[putptr] = x; // 在这里插入元素
            if (++putptr == items.length) putptr = 0;
            ++count;
            notempty.signal(); // 通知消费者队列非空
        } finally {
            lock.unlock();
        }
    }

    public object take() throws interruptedexception {
        lock.lock();
        try {
            while (count == 0) // 如果队列为空,则等待
                notempty.await();
            object x = items[takeptr]; // 在这里取出元素
            if (++takeptr == items.length) takeptr = 0;
            --count;
            notfull.signal(); // 通知生产者队列未满
            return x;
        } finally {
            lock.unlock();
        }
    }
}

在这个例子中,消费者在 notempty 条件上等待,而生产者在 notfull 条件上等待。当队列状态改变时(例如,生产者添加了一个元素或消费者取出一个元素),相应的条件会被信号唤醒,这样等待的线程就可以重新获取锁并继续执行。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com