原理介绍
一个由链表(单向链表)结构组成的有界阻塞队列。此队列的默认和最大长度为Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。
双锁(ReentrantLock):takeLock、putLock,允许读写并行.
原理图
源码分析
类图
类图
核心方法
入队
offer(E e)
向队列尾部插入一个元素,如果队列有空闲容量则插入成功后返回 true,如果队列已满则丢弃当前元素然后返回false。该方法是非阻塞的,直接返回。
put(E e)
向队列尾部插入一个元素,如果队列有空闲则插入后直接返回true,如果队列已满则阻塞当前线程直到队列有空闲插入成功后返回true,如果在阻塞的时候被其它线程设置了中断标志,则被阻塞线程会抛出 InterruptedException 异常而返回,该方法是阻塞的。
出队
poll()
从队列头部获取并移除一个元素,如果队列为空则返回 null,该方法是不阻塞的。
take()
获取当前队列头部元素并从队列里面移除,如果队列为空则阻塞调用线程,直到队列不为空然后返回元素.如果在阻塞的时候被其它线程设置了中标志,则被阻塞线程会抛出InterruptedException 异常而返回。
remove(Object o)
删除队列里面指定元素,有则删除返回 true,没有则返回false。
获取
peek()
获取队列头部元素但是不从队列里面移除,如果队列为空则返回 null,该方法是不阻塞的。
FAQ
peek()中获取到first节点后,还要判断first是否为null?
判断队列是否为空和获取锁的过程不是原子操作,可能在获取takeLock之前,其他线程执行了poll或take操作,导致队列为空。
LinkedBlockingQueue与ArrayBlockingQueue的比较
ArrayBlockingQueue中在入队列和出队列操作过程中,使用的是同一个lock,读取和操作的都无法做到并行;LinkedBlockingQueue读取和插入操作所使用的锁是两个不同的lock,它们之间的操作互相不受干扰,因此两种操作可以并行完成。
LinkedBlockingQueue相比ArrayBlockingQueue具有更好的扩容性。ArrayBlockingQueue容量固定,可以更好的对吸能进行预测;LinkedBlockingQueue不指定,默认Integer.MAX_VALUE。创建节点是动态地,节点出队列会被GC回收,一种程度上可以理解为“无界队列”。任务多时,入队处理,可能会出现内存溢出的情况。
参考资料:
https://blog.csdn.net/u010887744/article/details/73010691
https://www.jianshu.com/p/cc2281b1a6bc
彩蛋:
对于经常逛github的猿猿(媛媛)们,octotree这个Chrome插件,使得github给人一种IDE的感觉,快来试试吧。
效果图:
资源地址:https://github.com/buunguyen/octotree
领取专属 10元无门槛券
私享最新 技术干货