Jdk1.6 JUC源码解析(12)-ArrayBlockingQueue
- ArrayBlockingQueue是一种基于数组实现的有界的阻塞队列。队列中的元素遵循先入先出(FIFO)的规则。新元素插入到队列的尾部,从队列头部取出元素。
- 和普通队列有所不同,该队列支持阻塞操作。比如从空队列中取元素,会导致当前线程阻塞,直到其他线程将元素放入队列;将元素插入已经满的队列,同样会导致当前线程阻塞,直到其他线程从队列中取出元素。
- ArrayBlockingQueue也支持公平和非公平策略(针对队列中元素的存取线程,也可认为是元素的生产者和消费者)。
- ArrayBlockingQueue继承了AbstractQueue并实现了BlockingQueue,AbstractQueue是Queue的公共骨架实现,这个不看了,简单看下BlockingQueue接口:
- public interface BlockingQueue<E> extends Queue<E> {
- /**
- * 将一个元素放入队列。
- * 成功返回true;失败抛IllegalStateException异常。
- */
- boolean add(E e);
- /**
- * 将一个元素放入队列。
- * 成功返回true;失败返回false。
- */
- boolean offer(E e);
- /**
- * 将一个元素放入队列。
- * 如果元素无法放入队列,当前操作线程会等待,直到元素可以放入队列。
- */
- void put(E e) throws InterruptedException;
- /**
- * 将一个元素放入队列。
- * 如果元素无法放入队列,当前操作线程会等待,直到元素可以放入队列或者
- * 给定的时间超时。
- * 成功返回true;超时返回false;
- */
- boolean offer(E e, long timeout, TimeUnit unit)
- throws InterruptedException;
- /**
- * 从队列头部获取并删除一个元素。
- * 如果无法获取元素,当前操作线程等待,直到有元素可以被获取。
- */
- E take() throws InterruptedException;
- /**
- * 从队列头部获取并删除一个元素。
- * 如果无法获取元素,当前操作线程等待,直到有元素可以被获取或者给定时间超时。
- * 如果超时,返回null。
- */
- E poll(long timeout, TimeUnit unit)
- throws InterruptedException;
- /**
- * 获取队列剩余容量。
- */
- int remainingCapacity();
- /**
- * 移除队列中和给定元素相同的元素。
- */
- boolean remove(Object o);
- /**
- * 判断队列中是否包含给定元素。
- */
- public boolean contains(Object o);
- /**
- * 移除队列中所有的可用元素,并把它们添加到给定集合。
- */
- int drainTo(Collection<? super E> c);
- /**
- * 移除队列中不超过给定数量的可用元素,并把它们添加到给定集合。
- */
- int drainTo(Collection<? super E> c, int maxElements);
- }
- 接下来看下ArrayBlockingQueue内部的数据结构:
- 继续看下ArrayBlockingQueue的重要方法,重点看下put和take,先看下put方法:
- public void put(E e) throws InterruptedException {
- if (e == null) throw new NullPointerException();
- final E[] items = this.items;
- final ReentrantLock lock = this.lock;
- //由于需要支持方法可中断行为,这里使用可中断的锁操作。
- lock.lockInterruptibly();
- try {
- try {
- while (count == items.length)
- notFull.await();//队列满时,在notFull条件上等待。
- } catch (InterruptedException ie) {
- notFull.signal(); // 被中断后,唤醒其他等待notFull条件的线程。
- throw ie;
- }
- insert(e);
- } finally {
- lock.unlock();
- }
- }
- /**
- * Circularly increment i.
- */
- final int inc(int i) {
- return (++i == items.length)? 0 : i;
- }
- /**
- * 在内部数组的putIndex位置插入元素,调整putIndex和count,然后唤醒notEmpty条件上等待的线程。
- * 本方法只有在持有锁的情况下才会被调用。
- */
- private void insert(E x) {
- items[putIndex] = x;
- putIndex = inc(putIndex);
- ++count;
- notEmpty.signal();
- }
再看下take方法:
- public E take() throws InterruptedException {
- final ReentrantLock lock = this.lock;
- lock.lockInterruptibly();
- try {
- try {
- while (count == 0)
- notEmpty.await();//队列空时,在notEmpty条件上等待。
- } catch (InterruptedException ie) {
- notEmpty.signal(); // 被中断后,唤醒其他等待notEmpty条件的线程。
- throw ie;
- }
- E x = extract();
- return x;
- } finally {
- lock.unlock();
- }
- }
- /**
- * 从takeInde的位置取出元素,增加takeIndex,减少count,唤醒在notFull上等待的线程。
- * 本方法只有在持有锁的情况下才会被调用。
- */
- private E extract() {
- final E[] items = this.items;
- E x = items[takeIndex];
- items[takeIndex] = null;
- takeIndex = inc(takeIndex);
- --count;
- notFull.signal();
- return x;
- }
- 其他方法的实现也都比较简单,不进行一一解析。最后注意一下,ArrayBlockingQueue的Iterator是弱一致的。
Jdk1.6 JUC源码解析(12)-ArrayBlockingQueue的更多相关文章
- Jdk1.6 JUC源码解析(13)-LinkedBlockingQueue
功能简介: LinkedBlockingQueue是一种基于单向链表实现的有界的(可选的,不指定默认int最大值)阻塞队列.队列中的元素遵循先入先出 (FIFO)的规则.新元素插入到队列的尾部,从队列 ...
- Jdk1.6 JUC源码解析(6)-locks-AbstractQueuedSynchronizer
功能简介: AbstractQueuedSynchronizer(以下简称AQS)是Java并发包提供的一个同步基础机制,是并发包中实现Lock和其他同步机制(如:Semaphore.CountDow ...
- Jdk1.6 JUC源码解析(7)-locks-ReentrantLock
功能简介: Java代码层面提供的锁机制,可做为Synchronized(jvm内置)的替代物,和Synchronized一样都是可重入的. 与Synchronized相比较而言,ReentrantL ...
- Jdk1.6 JUC源码解析(1)-atomic-AtomicXXX
转自:http://brokendreams.iteye.com/blog/2250109 功能简介: 原子量和普通变量相比,主要体现在读写的线程安全上.对原子量的是原子的(比如多线程下的共享变量i+ ...
- 【JUC源码解析】ScheduledThreadPoolExecutor
简介 它是一个线程池执行器(ThreadPoolExecutor),在给定的延迟(delay)后执行.在多线程或者对灵活性有要求的环境下,要优于java.util.Timer. 提交的任务在执行之前支 ...
- 【JUC源码解析】Exchanger
简介 Exchanger,并发工具类,用于线程间的数据交换. 使用 两个线程,两个缓冲区,一个线程往一个缓冲区里面填数据,另一个线程从另一个缓冲区里面取数据.当填数据的线程将缓冲区填满时,或者取数据的 ...
- 【JUC源码解析】SynchronousQueue
简介 SynchronousQueue是一种特殊的阻塞队列,该队列没有容量. [存数据线程]到达队列后,若发现没有[取数据线程]在此等待,则[存数据线程]便入队等待,直到有[取数据线程]来取数据,并释 ...
- 【JUC源码解析】ForkJoinPool
简介 ForkJoin 框架,另一种风格的线程池(相比于ThreadPoolExecutor),采用分治算法,工作密取策略,极大地提高了并行性.对于那种大任务分割小任务的场景(分治)尤其有用. 框架图 ...
- 【JUC源码解析】DelayQueue
简介 基于优先级队列,以过期时间作为排序的基准,剩余时间最少的元素排在队首.只有过期的元素才能出队,在此之前,线程等待. 源码解析 属性 private final transient Reentra ...
随机推荐
- js移动端横竖屏检测
方法一:用resize事件来判断,利用屏幕的宽高比,来判断横竖屏 (兼容性较好) (function () { var updateOrientation = function () { var or ...
- Sublime Text 3常用插件
操作:按下Ctrl+Shift+P调出命令面板 输入install 调出 Install Package 选项并回车,然后在列表中选中要安装的插件. 常用插件: 1---- Bracket Highl ...
- 如何用Android Studio查看build.gradle源码
上一篇博客里讲过 build.gradle 里的每一行代码基本都是在调用一个方法,既然是这样,我们就可以用 android studio(下面简称as) 去查看它源码的方法注释说明,这样就可以理解每个 ...
- 通过哨兵机制实现Redis主从配置以及java调用
Redis版本:3.0.7 操作环境:Linux 一.redis 主从配置的作用是什么 redis主从配置,配置master 只能为写,slave只能为读,在客户端对poolconnect请求时候,, ...
- js两个判断&&的值与||的值
var value1="val1"; var value2="val2"; alert(value1&&value2); //结果为val ...
- js根据条件json生成随机json:randomjson
前端开发中,在做前后端分离的时候,经常需要手写json数据,有3个问题特别揪心: 1,数据是写死的,不能按一定的条件随机生成长度不一,内容不一的数据 2,写数组的时候,如果有很多条,需要一条一条地写, ...
- Android使用本地广播
Android本地广播学习中一直被忽略,今天用到了,Mark一下 1.本地广播的定义和普通广播一样 例如 public class WakeTimesBroadcastReceiver extends ...
- windows系统System32中各种实用的工具
工具类 这些工具可以直接打开运行 输入名字就可以调出来了 我还会上传一个java程序,运行后会显示一个界面,直接调用这些工具 1.SnippingTool.exe 截图 2.calc.exe ...
- Nature:新发现挑战神经元作用传统理论 [转自科学网]
美德科学家独立进行的两项最新研究表明,单个神经元的激发就足以影响学习和行为.这一结论挑战了人们长期以来的认识,即数千个神经元的有序排列才能够产生一个行为反应.这两篇论文12月19日在线发表于<自 ...
- .Net 官方学习文档
.Net 官方学习文档:https://docs.microsoft.com/zh-cn/dotnet/articles/welcome