3

BlockingQueue

BlockingQueue是线程安全的存取队列,继承了Queue。

使用场景

消费者生产者模式。

  • 生产者,一直会往队列里扔数据,直到队列满了,开始阻塞,等待消费者取数据。
  • 消费者,一直会从队列里取数据,直到队列空了,开始阻塞,等待生产者扔数据。

接口

clipboard.png

插入方法

  • add:阻塞队列满了,抛出IllegalStateException异常。成功返回true。
  • offer:插入成功,返回true,插入失败,返回false。
  • put:阻塞队列满了,就等到,可被中断,抛出InterruptedException异常

移除方法

  • remove:成功返回true,为空抛出NoSuchElementException异常
  • poll:如果队列不为空,移除并返回头结点,如果队列为空,返回null
  • take:如果队列不为空,移除并返回头结点,如果队列为空,则等待,可被中断,抛出InterruptedException异常

检查方法:

  • element:如果队列不为空,返回头结点但不删除,如果队列为空,抛出NoSuchElementException异常。
  • peek:如果队列不为空,返回头结点但不删除,如果队列为空,返回null

子类

  • ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
  • LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
  • PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
  • DelayQueue:一个使用优先级排序实现的无界阻塞队列。
  • SynchronousQueue:一个不存储元素的阻塞队列。
  • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
  • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

ArrayBlockingQueue

先进先出,初始化必须给数组大小,只有一个锁。

ArrayBlockingQueue数据结构

  • Object[] items:存放元素的数组
  • int takeIndex:下一个读操作的位置
  • int putIndex:下一个写操作的位置
  • int count:数组中元素的数量
  • ReentrantLock lock:同步器
  • Condition notEmpty:数组空了,读等待。写的时候,唤醒
  • Condition notFull:数组满了,写等待。读的时候,唤醒

ArrayBlockingQueue原理

put先放入数组,满了请求放入Condition等待数组空。take相反,数组空了,请求放入队列,等待队列有内容。
clipboard.png

LinkedBlockingQueue

先进先出,初始化没有给链表带下,默认为Integer.MAX_VALUE,有两个锁。

LinkedBlockingQueue与ArrayBlockingQueue

  • 链表是2个锁,读写各一个,数组的是1个锁
  • 链表操作时需要封装成node,产生大量的node,GC耗时,数组直接操作,性能更高
  • 链表的生产者的速度大于消费者时,可能内存溢出

PriorityBlockingQueue

可以直接通过Comparator或者Collection的Comparator进行排序,一个锁。

DelayQueue

DelayQueue中的对象必须实现Delayed接口,延时取元素。
使用场景:

  1. 订单到期未付款,取消订单
  2. 删除过期的缓存

SynchronousQueue

因为不存储数据,所以每一次put,都要等待一个take。

LinkedTransferQueue

先进先出,如果消费者在等待接收元素,transfer方法把元素直接给消费者,如果没有,则放对队列的尾节点,并等到消费结束后返回。tryTransfer无论消费者是否消费,都直接返回。

LinkedBlockingDeque

头部和尾部,都可以添加或移除元素。工作密取,就是用这个


大军
847 声望183 粉丝

学而不思则罔,思而不学则殆