一、类结构图
二、实现类介绍
1. ArrayBlockingQueue
:
基于数组结构的有界阻塞队列(长度不可变);
2. LinkedBlockingQueue
:
基于链表结构的有界阻塞队列(默认容量 Integer.MAX_VALUE);
3. LinkedTransferQueue
:
基于链表结构的无界阻塞/传递队列;
4. LinkedBlockingDeque
:
基于链表结构的有界阻塞双端队列(默认容量 Integer.MAX_VALUE);
5. SynchronousQueue
:
不存储元素的阻塞/传递队列;(也就是没有容量的队列。使用地方:线程池的核心容量满了 直接添加到线程直到达到最大线程池数量 后启用拒绝策略
6. PriorityBlockingQueue
:
支持优先级排序的无界阻塞队列;
DelayQueue
:
支持延时获取元素的无界阻塞队列;
注:无锁采用CAS 也是线程安全的
队列 | 有界性 | 锁 | 数据结构 |
---|---|---|---|
ArrayBlockingQueue | bounded | 加锁 | arraylist |
LinkedBlockingQueue | optionally-bounded | 加锁 | linkedlist |
ConcurrentLinkedQueue | unbounded | 无锁 | linkedlist |
LinkedTransferQueue | unbounded | 无锁 | linkedlist |
PriorityBlockingQueue | unbounded | 加锁 | heap |
DelayQueue | unbounded | 加锁 | heap |
三、常用方法介绍
public interface BlockingQueue<E> extends Queue<E> {
/*抛异常系列*/
boolean add(E e);
E remove();
E element();
/*特定值系列*/
boolean offer(E e);
E poll();
E peek();
/*阻塞系列*/
void put(E e) throws InterruptedException;
E take() throws InterruptedException;
/* 超时系列*/
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
E poll(long timeout, TimeUnit unit) throws InterruptedException;
/*其它方法*/
int remainingCapacity(); //剩余容量
boolean contains(0bject o); //是否包含给定元素
boolean remove(object o); //移除与之匹配的第个元素
int drainTo(Collection<? super E> c); //转移元素到给定集合,返回己转移的数量
int drainTo(Collection<? super E> c, int maxElements); //限制最大转移数量
}
失败抛出异常 | 失败返回false | 阻塞方法 | 等待一定时间 失败返回false | |
---|---|---|---|---|
Insert | add(e) | offer(e) | put(e) | offer(e, time, unit) |
Remove | remove( ) | poll() | take() | poll(time,unit) |
Examine | element() | peek() | not applicable | not applicable |
四、实现方式
ArrayBlockingQueue: 数组+锁实现
LinkedBlockingQueue: 链表+锁实现
PriorityBlockingQueue: 堆 + 锁
DelayQueue:PriorityQueue + 锁
PriorityQueue: Heap = 完全二叉树 + 特性(小根堆:根比儿子小, 大根堆: 。。)
五、性能
1.锁的性能消耗
2.Single Writer Principle(单写原则)
1)若只有一个线程对资源进行写操作,无需CPU浪费管理资源争夺或上下文切换
2)多个线程如果同时写同一个资源,必有争夺,就需要用锁或乐观锁等堵塞方法
使用非阻塞:CAS
3. Cpu Cache层次优化
CPU 缓存(Cache Memory)是位于 CPU 与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多。
高速缓存的出现主要是为了解决 CPU 运算速度与内存读写速度不匹配的矛盾,因为 CPU 运算速度要比内存读写速度快很多,这样会使 CPU 花费很长时间等待数据到来或把数据写入内存。
在缓存中的数据是内存中的一小部分,但这一小部分是短时间内 CPU 即将访问的,当 CPU 调用大量数据时,就可避开内存直接从缓存中调用,从而加快读取速度。
缓存是按行 (按行访问数组要比按列访问要快)
本文只是简要接收具体请参考其他博客如https://www.cnblogs.com/cyfonly/p/5800758.html
在内存中每行会进行缓存
如果cpu core1 写 cpu core2读
字段列表
在字段内存中分配的大小
同一个缓存行中一读 一写
解决方法
- 填充字段
- 填充内部类
4.其他优化策略
具体请百度
环形队列预分配,零GC
批量生产及消费
位运算,而非普通的求余取模(%) 有条件限制取末必须为2^N的数如 101%4 =101&(4-1)