Java 集合框架分析:ArrayBlockingQueue java1.8

时间:2022-05-30 17:53:04

相关文章:
Java 集合框架分析:Set
http://blog.csdn.net/youyou1543724847/article/details/52733723
Java 集合框架分析:LinkedList
http://blog.csdn.net/youyou1543724847/article/details/52734935
Java 集合框架分析:DelayQueue
http://blog.csdn.net/youyou1543724847/article/details/52176504
Java 集合框架分析:ArrayBlockingQueue
http://blog.csdn.net/youyou1543724847/article/details/52174308
Java 集合框架分析:ArrayDeque
http://blog.csdn.net/youyou1543724847/article/details/52170026
Java 集合框架分析:PriorityBlockingQueue
http://blog.csdn.net/youyou1543724847/article/details/52166985
Java 集合框架分析:JAVA Queue源码分析
http://blog.csdn.net/youyou1543724847/article/details/52164895
Java 集合框架分析:关于Set,Map集合中元素判等的方式
http://blog.csdn.net/youyou1543724847/article/details/52733766
Java 集合框架分析:ConcurrentModificationException
http://blog.csdn.net/youyou1543724847/article/details/52733780
Java 集合框架分析:线程安全的集合
http://blog.csdn.net/youyou1543724847/article/details/52734876
Java 集合框架分析:JAVA集合中的一些边边角角的知识
http://blog.csdn.net/youyou1543724847/article/details/52734918

ArrayBlockingQueue
目录
1.ArrayBlockingQueue简介
2.主要方法
3.和其他相关集合的比较
4.总结


1.ArrayBlockingQueue简介
线程安全的先进先出队列,并且是属于有界的队列,一个典型的有界缓冲区。支持公平锁的存、取操作。


2.主要方法
先看看主要的成员变量:
takeindex,putinex就是对应于ArrayDeque里的head,tail.另外为了保护items的多线程安全,用lock来维护,同时使用两个关联的Condition来形成两个等待队列。其实要理解ArrayBlockingQueue,理解了Condition就可以了,这里可以看我上一篇文章“conditon java1.8

    final Object[] items;
int takeIndex;
int putIndex;
int count;
final ReentrantLock lock;
private final Condition notEmpty;
private final Condition notFull;

插入:阻塞版本的
其实逻辑比较简单,如果当前队列为空满,则当当前线程放在满的等待集合中,否则插入一个元素(通过enquue,在里头唤醒一个睡眠的线程去取)

    public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}

删除:阻塞版本的
形式和put类似,就不多说了

    public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}

方法的总结:
take ,put :阻塞版本的
offer,poll:非阻塞版本的
offer(long timeout, TimeUnit unit),poll(long timeout, TimeUnit unit):带有最长等待时间的
add,remove:非阻塞的,抛出异常的(取时队列满,拿时队列空)


3.和其他相关集合的比较
PriorityQueue:基于堆的非阻塞*队列
PriorityBlockQueue:基于堆的阻塞的*队列
ArrayDeque:非阻塞的,*的
ArrayBlockingQueue:基于数组的有界的阻塞队列

比较了这么多,问一句:JAVA集合框架中,没普通的传统的简单的队列么?非阻塞的,有界的
答案:是没有的或者说没有直接的。你要知道有界的又不是阻塞类型的结构,如Queue,如果满了,你还是要添加,这时,就要两个选择:

  1. 直接返回null;
  2. 阻塞起来。

为了实现代码的复用,ArrayBlockingQueue就是都实现了这两种策略,对应的API就是take,put(阻塞的)poll,offer(非阻塞的)。
唯一的区别就是所有的操作都是加锁的,从这个角度来说,如果在单线程中使用,这就有点不划算了。

不过有ArrayDeque,为什么没有响应的ArrayBlockingDeque呢?


总结

  1. ArrayBlockingQueue排队的公平性是由RenetrantLock的公平性来保证的,这是可选选项,在构造Queue时,设置。
  2. ArrayBlockingQueue有界的,其存取方法有阻塞、非阻塞版本。
  3. 不允许null元素
  4. ArrayBlockingQueue的阻塞形式的方法take,put,offer(long timeout, TimeUnit unit),poll(long timeout, TimeUnit unit)都是使用lockInterruptibly获取锁的。即要么获取锁继续操作,要么在等待锁时,被中断,通过抛出InterruptedException异常返回(抛出异常,中断标志被清除)。