🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] > 本文视频讲解:https://www.bilibili.com/video/BV1Lb4y1d7L7 ## 什么是阻塞队列 阻塞队列是一个在队列基础上又支持了两个附加操作的队列,常应用于解耦。 两个附加操作: 1. 支持阻塞的插入方法:队列满时,队列会阻塞插入元素的线程,直到队列不满。 2. 支持阻塞的移除方法:队列空时,获取元素的线程会等待队列变为非空。 阻塞队列是哪里用到的?阻塞队列是线程池的自定义参数之一。<br> 和JDK集合包中的Queue接兼容,同时在其基础上增加了阻塞功能。 定义的接口,而pu(.)是阻塞的。 ### 说一下JUC中BlockingQueue接口主要的方法和特点? 条件: notEmpty:非空状态,take()线程可以在队列中取数据; notFull:未满装填,put()线程可以在队列中放数据; #### 说一说BlockingQueue常 用的实现类? **说一下ArrayBlockingQueue的设计?** > 一个对象数组 + 一把锁 + 两个条件 是一个用数组实现的有界阻塞队列,此队列按照先进先出(FIFO)的原则对元素进行排序。支持公平锁和非公平锁。 1. ArrayBlockingQueue是一个用数组实现的环形队列,在构造方法中,会要求传入数组的容量。 2. 入队与出队都用同一把锁只有入队高并发或出队高并发的情况下,操作数组不需要扩容,性能很高。 > 注:每一个线程在获取锁的时候可能都会排队等待,如果在等待时间上,先获取锁的线程的请求一定先被满足,那么这个锁就是公平的。反之,这个锁就是不公平的。公平的获取锁,也就是当前等待时间最长的线程先获取锁 ##### 说一下LinkedBlockingQueue的设计? ``` public class LinkedBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable { /** The capacity bound, or Integer.MAX_VALUE if none */ private final int capacity; /** Current number of elements */ private final AtomicInteger count = new AtomicInteger(); /** * Head of linked list. * Invariant: head.item == null */ transient Node<E> head; /** * Tail of linked list. * Invariant: last.next == null */ private transient Node<E> last; /** Lock held by take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */ private final Condition notEmpty = takeLock.newCondition(); /** Lock held by put, offer, etc */ private final ReentrantLock putLock = new ReentrantLock(); /** Wait queue for waiting puts */ private final Condition notFull = putLock.newCondition(); …… } ``` - 两把锁:put()操作和take()操作,分别对应一把锁,本质上操作的是Node对象; - 相互通知:put()线程未满,通知其他put()线程,会通知take()线程; ##### 说-下PriorityBlockingQueue的设计? #### SynchronousQueue ![](https://img.kancloud.cn/1f/90/1f9086d453fd2c3a2cbee8a865e20119_1136x362.png) SynchronousQueue: 一个不存储元素的阻塞队列,每一个put()操作必须等待take()操作,否则不能添加元素。支持公平锁和非公平锁。SynchronousQueue的一个使用场景是在线程池里。Executors.newCachedThreadPool()就使用了SynchronousQueue,这个线程池根据需要(新任务到来时)创建新的线程,如果有空闲线程则会重复使用,线程空闲了60秒后会被回收。 ### 应用场景 ## 总结 ![](https://img.kancloud.cn/03/f0/03f0767de4929e3c4a2bea3c5041af75_909x465.png)