阻塞队列BlockingQueue

数组阻塞队列ArrayBlockingQueue:

  1. 特点:先进先出(FIFO)、读写互斥
  2. 数据结构:静态数组,容量固定必须指定长度,没有扩容机制,没有元素的位置使用null占位(为null的位置也是占用着数据空间)
  3. 锁:ReentrantLock存取是同一把锁,操作的是同一个对象数组
  4. 阻塞:
    • Condition notEmpty;当出队时(取出数据),当队列count(队列的元素个数)为0,没有数据可取,这时会阻塞该对象上
    • Condition notFull;当入队时(放入数据),当队列count(队列的元素个数)和数组的length相等时,放不进元素,这时会阻塞在该对象上
  5. 入队:从队首开始添加元素,记录putIndex(到队尾时置为0),每次入队一个数据时,不管是否阻塞,都会唤醒一次Condition notEmpty
  6. 出队:从队首开始取元素,记录takeIndex,唤醒Condition notFull

链表阻塞队列LinkedBlockingQueue:

  1. 特点:先进先出(FIFO)、读写互斥
  2. 数据结构:链表Node,可以指定容量,不指定时默认为Integer.MAX_VALUE,内部类Node存储元素
  3. 锁分离:存取互不排斥,操作的是不同的Node对象,取:ReentrantLock takeLock,存:ReentrantLock putLock
  4. 阻塞:和ArrayBlockingQueue一致
  5. 入队:队尾入队,记录last节点
  6. 出队:队首出队,记录head几点
  7. 删除元素时,存取都会加锁

同步队列SynchronousQueue:

  1. 两种模式(通过一个boolean属性指定):
    • 公平模式(链表):TransferQueue,节点使用QNode,队尾匹配,队头出队,先进先出(FIFO)
    • 非公平模式(栈):TransferStack,节点使用SNode,栈顶匹配,出入口都在栈顶,后进先出(LIFO)
  2. 存取数据:
    • 存取都是调用Transferer.transfer()函数,区分存取是根据是否携带了数据e
    • put、offer为生产者,携带了数据e,为Data模式,设置到QNode/SNode属性中
    • take、poll为消费者,不携带数据e,为REQUEST模式,设置到QNode/SNode属性中
    • 没存或取到数据会阻塞
  3. 数据结构:链表Node
  4. 锁:CAS + 自旋
  5. 阻塞:LockSupport

LinkedTransferQueue

  1. 数据结构:链表Node
  2. 锁:CAS + 自旋
  3. 阻塞:LockSupport
  4. 放入元素:往队列中放元素可以自己控制是否需要阻塞队列
  5. 取元素:没取到数据时会阻塞
  6. 特点:与SynchronousQueue基本一样

优先级的阻塞队列PriorityBlockingQueue:

  1. 数据结构:数组 + 平衡二叉树堆,可以指定初始容量,会自动扩容,最大容量为Integer.MAX_VALUE
  2. 锁:ReentrantLock存取是同一把锁
  3. 阻塞:Condition notEmpty,出队,队列为空时阻塞
  4. 入队:
    • 不阻塞,永远返回成功,无界(逻辑上是无界,有可能由于资源耗尽导致OutOfMemoryError)
    • 根据比较器进行堆化:根据二叉堆进行排序,自下而上
  5. 出队:
    • 弹出堆顶元素
    • 堆尾元素放到堆顶
    • 自上而下堆化,堆化:堆上的元素根据较器对元素进行排序
    • 为空则阻塞
  6. 按照优先级排序,创建PriorityBlockingQueue队列时可以传入一个比较器Comparator,优先级最高的会先出队。

链表阻塞双端队列LinkedBlockingDeque:

  1. 数据结构:链表Node,可以指定容量,不指定时默认为Integer.MAX_VALUE,内部类Node存储元素
  2. 锁:ReentrantLock存取是同一把锁
  3. 阻塞:
    • Condition notEmpty;当出队时(取出数据),当队列count(队列的元素个数)为0,没有数据可取,这时会阻塞该对象上
    • Condition notFull;当入队时(放入数据),当队列count(队列的元素个数)和数组的length相等时,放不进元素,这时会阻塞在该对象上
  4. 入队:队首队尾都可以
  5. 出队:队首队尾都可以

延迟队列DelayQueue:

  1. 数据结构:PriorityQueue优先级队列,与PriorityBlockingQueue类似,但是没有阻塞功能
  2. 锁:ReentrantLock
  3. 阻塞:Condition available
  4. 队列不允许有空元素,而且放入的元素必须实现Delayed接口
  5. 入队:不阻塞,无界队列,与优先级队列入队相同,唤醒出队的Condition available
  6. 出队:
    1. 为空则阻塞available
    2. 检查堆顶元素过期时间
      • 小于等于0,则取出
      • 大于0,则阻塞,然后判断leader线程是否为空
        • 不为空(已经有线程正在阻塞),考虑到优先级的问题,所以直接阻塞
        • 为空,则将当前线程置为leader,并按照过期时间进行阻塞,到期后会自动唤醒
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值