阻塞队列 - BlockingQueue
线程通信的一个工具。在任意时刻,不管并发有多高,在单JVM上面,同一时间永远只有一个线程能够对队列进行入队或者出队操作。
1. 线程安全的队列;
2. 队列类型:无限队列、有限队列;
常见的4种阻塞队列:
- ArrayBlockingQueue 由数组支持的有界队列
- LinkedBlockingQueue 由链接节点支持的可选有界队列
- PriorityBlockingQueue 由优先级堆支持的无解优先级队列
- DelayQueue 由优先级堆支持的、基于时间的调度队列
应用场景:
1. 线程池,SpringCloud-Eureka的三级缓存,Nacos、Netty、MQ(RocketMQ)、生产者与消费者模型
例如ArrayBlockingQueue,其本质内部有一个ReetrantLock,如果线程想要操作这个队列之前,必须先获得这把锁。
在BlockingQue内部执行deque和enque的时候,如果当前队列判了,会有一个await的操作,也就是上述列出的一张图的代码。
在这里面可以看到具体得执行流程。
这里要提出一个等待队列的概念,之前讲AQS的时候只讲到同步队列,同步队列是真正可以拿到cpu去执行线程的队列。而等待队列用于BlockingQueue可以很巧合地实现生产者和消费者之前入队和出队的操作,里面有两个内部变量notFull,notEmpty,有这两个条件变量在,可以很巧合地通知通知机制,消费者消费后去通知生产者进入同步队列执行放入数据到等待队列,生产者生产数据后可以去通知消费者到同步队列执行从等待队列取出数据。总之生产者和消费者总是在等待队列和同步队列之间来回切换。
下面见ArrayBlockingQueue的构造器和put方法。
public ArrayBlockingQueue(int capacity, boolean fair) { if(capacity <= 0){ throw new IllegalArgumentException(); } this.items = new Object[capacity]; lock = new ReentrantLock(fair); // 创建一把锁 notEmpty = lock.newCondition(); // 条件对象 notFull = lock.newCondition(); // 条件对象 } public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; // producer加锁 lock.lockInterruptibly(); try { while(count == items.length) notFull.await(); enqueue(e); } finally { lock.unlock(); } }
End!
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
2020-11-05 Java核心类库(上)学习笔记
2020-11-05 Redis在项目中的地位及使用场景剖析
2020-11-05 单例模式的优缺点和使用场景