前面我们介绍的LinkedBlockingQueue的源码,这篇文章我们一起研究下ArrayBlockingQueue的源码
(1)LinkedBlockingQueue源码解析
(2)ArrayBlockingQueue源码解析
从语义上看,ArrayBlockingQueue底层是基于数组实现的,而LinkedBlockingQueue底层是基于链表实现的(实际是封装为Node,类似C语言的节点),两者实现方式的不同,也造成了性能和效率的差异。
我们首先来介绍下几个重要的类变量:
/**实际承载队列元素的数组 */ final Object[] items; /** 消费者序列号 for next take, poll, peek or remove */ int takeIndex; /**生产者序列号 for next put, offer, or add */ int putIndex; /** 队列大小 */ int count; /* * 并发的控制采用两种condition的逻辑,也就是俗称的”两把锁“ */ /** Main lock guarding all access */ final ReentrantLock lock; /** 消费者锁 */ private final Condition notEmpty; /** 生产者锁 */ private final Condition notFull;
下面看几个核心的私有方法:
/** * 入队时的核心方法,block内部维护了一个putIndex,用来标示 * 当前允许插入的下标 * 一旦插入后,等待notEmpty的线程就被唤醒,即可以消费了 */ private void insert(E x) { items[putIndex] = x; putIndex = inc(putIndex); ++count; notEmpty.signal(); } /** * 出对时的核心方法,同insert,block内部维护了takeIndex * 用来标示当前允许出对的下标 * 而一旦出对,等待notFull的线程也被唤醒,即可以生产了 */ private E extract() { final Object[] items = this.items; E x = this.<E>cast(items[takeIndex]); items[takeIndex] = null; takeIndex = inc(takeIndex); --count; notFull.signal(); return x; }
可见,ArrayBlockingQueue的入队和出对,都是基于数组的实现,而LinkedBlockingQueue则是对元素封装成Node后,再进行其他操作,所以在大量线程操作队列时,ArrayBlockingQueue的性能要优于LinkedBlockingQueue。
ArrayBlockingQueue是固定大小的队列,初始化时,必须要传入队列的容量。
下面我们列举ArrayBlockingQueue提供的几个队列方法
一 offer
public boolean offer(E e) { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lock(); try { if (count == items.length) return false; else { insert(e); return true; } } finally { lock.unlock(); } }
offer提供了两个重载的方法,上面的这个是不带参数的,如果当前队列已饱和,则直接返回false,而另一个offer方法中可传入等待时间,如果在指定的等待时间内,仍然等不到队列有空的位置,则直接返回false
public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { checkNotNull(e); long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) { if (nanos <= 0) return false; nanos = notFull.awaitNanos(nanos); } insert(e); return true; } finally { lock.unlock(); } }
二 put
public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); insert(e); } finally { lock.unlock(); } }
可见put方法在队列饱和时,是阻塞的,除非队列不饱和
三 poll和take
public E poll() { final ReentrantLock lock = this.lock; lock.lock(); try { return (count == 0) ? null : extract(); } finally { lock.unlock(); } } public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) notEmpty.await(); return extract(); } finally { lock.unlock(); } }
poll和take类似,不同点在于poll在队列空时,是不阻塞的,但是take会一直阻塞直到队列非空
四 peek
public E peek() { final ReentrantLock lock = this.lock; lock.lock(); try { return (count == 0) ? null : itemAt(takeIndex); } finally { lock.unlock(); } }
peek方法只是返回队首元素,但是不移除
此外,还提供了一些实用的方法,toArray(将队列转换为数组),clear(清空队列),drainTo(将队列转移到集合中)
相关推荐
ArrayBlockingQueue源码解析__动力节点共23页.pdf.zip
ArrayBlockingQueue源码分析.docx
今天小编就为大家分享一篇关于Java源码解析阻塞队列ArrayBlockingQueue常用方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解
今天小编就为大家分享一篇关于Java源码解析阻塞队列ArrayBlockingQueue介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
今天小编就为大家分享一篇关于Java源码解析阻塞队列ArrayBlockingQueue功能简介,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
Java concurrency集合之ArrayBlockingQueue_动力节点Java学院整理,动力节点口口相传的Java黄埔军校
主要介绍了java并发之ArrayBlockingQueue详细介绍的相关资料,需要的朋友可以参考下
主要介绍了详细分析Java并发集合ArrayBlockingQueue的用法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
主要介绍了java中LinkedBlockingQueue与ArrayBlockingQueue的异同,需要的朋友可以参考下
在前面的的文章,写了一个带有缓冲区的队列,是用JAVA的Lock下的Condition实现的,但是JAVA类中提供了这项功能,是ArrayBlockingQueue, ArrayBlockingQueue是由数组支持的有界阻塞队列,次队列按照FIFO(先进先...
java ...[ArrayBlockingQueue] [ConcurrentLinkedQueue] [PriorityBlockingQueue] [DelayQueue] 并发安全集合 [HashMap, ConcurrentHashMap源码] [ArrayList, LinkedList, CopyOnWriteArrayList源码]
ArrayBlockingQueue是一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。队列的头部 是在队列中存在时间最长的元素
Java并发编程学习宝典(漫画版),Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习...
20.并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解 21.线程池ThreadPoolExecutor实现原理 22.线程池之ScheduledThreadPoolExecutor 23.FutureTask基本操作总结 24.Java中atomic包中的原子操作类...
囊括了java.util.concurrent包中大部分类的源码分析,其中涉及automic包,locks包(AbstractQueuedSynchronizer、ReentrantLock、ReentrantReadWriteLock、LockSupport等),queue(ArrayBlockingQueue、...
bitset源码Java源码分析 基础集合列表 ArrayList (done) Vector (done) LinkedList (done) Stack (done) ReferenceQueue (done) ArrayDeque (done) Set HashSet (done) TreeSet (done) LinkedHashSet (done) BitSet ...