resdis的阻塞队列 阻塞队列实现_resdis的阻塞队列

特点

  • 阻塞队列继承自队列,和JDK中的Queue接口兼容同时在其基础上添加了阻塞功能
  • 入队操作提供了add(),offer(),put()方法,其中add()和offe()方法是非阻塞的,put()方法是阻塞的,通过抛出的异常便可以分辨出来
  • add()方法在队列满时会抛出异常,而offer方法则是返回失败
  • 出队提供了remove()、take()和poll()方法,其中remove方法是非阻塞,剩余两个则是阻塞的

BlockingQueue实现类

resdis的阻塞队列 阻塞队列实现_resdis的阻塞队列_02


主要体现在存储结构或对元素操作的不同,但是对于take与put操作的原理,大体上是相同的

  • ArrayBlockingQueue
  1. 一个对象数组(固定大小)+一把锁(可重复锁)+两个条件(不空,不满)
  2. 数组,必须指定大小,即容量有限
  3. 不需要做扩容,只有一把锁,所以入队和出队只能一个是高并发

    final数组,final可重复锁 两个条件:不空,不满

put方法

resdis的阻塞队列 阻塞队列实现_spring_03


take方法

resdis的阻塞队列 阻塞队列实现_出队_04

  • LinkedBlockingQueue
  1. 为了提高并发度,使用两把锁,分别控制队头、队尾的操作,所以put()和put()、take和take()互斥,put()和take()不互斥。但是对于count变量,双方都需要操作,所以必须是原子类型
  2. 采用了链表结构,最大容量为整数最大值,可看做无限容量
  3. 不仅put会通知take,take也会通知put。当put发现非满的时候,也会通知其他线程;同理,take也是
  4. 因为各自拿了一把锁,所以当需要调用对方的condition的sigal时,还必须加上对方的锁,就是sigalNotEmpty和signalNotFull方法
  • LinkedBolockingQueue是一种基于单向链表的阻塞队列。因为队头和队尾是两个指针分开操作的,所以用了两把锁和两个条件,同时有一个AtomicInteger的原子变量记录count数
  • 在其构造方法中,也可以指定队列的总容量,如果不指定,则用Integer的最大数
    take方法

    当take发现非空的时候,也会通知其他线程
    put方法

    put在未满时,也会通知其他put线程
    singal

    因为各自拿了一把锁,所以当需要调用对方的condition的signal时,还必须再加上对方的锁,就是上图中两个方法.
  • PriorityBlockingQueue
  1. 在阻塞的实现方面,和ArrayBlockingQueue的机制类似,主要区别是用数组实现了一个二叉堆,从而实现按优先级出队列
  2. 没有notFull条件,当元素个数超出容量时,进行扩容操作
  3. resdis的阻塞队列 阻塞队列实现_resdis的阻塞队列_05


  • priorityBlockingQueue按照元素的优先级从小到大出队列
  • 两个元素之间需要可以比较大小,并实现Comparable接口
    take方法
  • resdis的阻塞队列 阻塞队列实现_出队_06


  • resdis的阻塞队列 阻塞队列实现_出队_07

  • put方法
    默认容量为11,超出这个数时进行扩容
  • resdis的阻塞队列 阻塞队列实现_出队_08

  • 只有notEmpty条件,没有notFull条件