linkedblockingqueue 后 take 不消化_阻塞队列(3)LinkedBlockingQueue源码详解

问题

ed95ce066185b6064696ef5ef46be76b.png

输入图片说明

  • LinkedBlockingQueue是什么?
  • 优缺点?
  • 应用场景?
  • 源码实现?
  • 个人启发?

LinkedBlockingQueue

双向并发阻塞队列。

所谓双向是指可以从队列的头和尾同时操作,并发只是线程安全的实现,阻塞允许在入队出队不满足条件时挂起线程,这里说的队列是指支持FIFO/FILO实现的链表。

  1. 要想支持阻塞功能,队列的容量一定是固定的,否则无法在入队的时候挂起线程。也就是capacity是final类型的。
  2. 既然是双向链表,每一个结点就需要前后两个引用,这样才能将所有元素串联起来,支持双向遍历。也即需要prev/next两个引用。
  3. 双向链表需要头尾同时操作,所以需要first/last两个节点,当然可以参考LinkedList那样采用一个节点的双向来完成,那样实现起来就稍微麻烦点。
  4. 既然要支持阻塞功能,就需要锁和条件变量来挂起线程。这里使用一个锁两个条件变量来完成此功能。

优缺点

优点当然是功能足够强大,同时由于采用一个独占锁,因此实现起来也比较简单。所有对队列的操作都加锁就可以完成。同时独占锁也能够很好的支持双向阻塞的特性。

凡事有利必有弊。缺点就是由于独占锁,所以不能同时进行两个操作,这样性能上就大打折扣。从性能的角度讲LinkedBlockingDeque要比LinkedQueue要低很多,比CocurrentLinkedQueue就低更多了,这在高并发情况下就比较明显了。

前面分析足够多的Queue实现后,LinkedBlockingDeque的原理和实现就不值得一提了,无非是在独占锁下对一个链表的普通操作。

核心方法

在使用之前,让我们一起看一个简单的例子。

添加元素

0ecf5412fb383bac60bd635c46b46c22.png

移除元素

93bff1ae65d0445c9c21843f1c45132d.png

例子

我们实现 put 和 take,分别模拟写入工作者,和取出工作者。

package com.github.houbb.lock.test.lock;import java.util.concurrent.*;/** * @author binbin.hou * @since 1.0.0 */public class LinkedBlockingQueueDemo {    private BlockingQueue queue = new LinkedBlockingQueue<>(3);    public void put(final String put) throws InterruptedException {        System.out.println("设置开始");        TimeUnit.SECONDS.sleep(1);        queue.put(put);        System.out.println("设置完成: " + put);    }    public void take() throws InterruptedException {        System.out.println("获取开始");        String take = queue.take();        System.out.println("获取成功: " + take);    }}

测试代码:

public static void main(String[] args) {    final LinkedBlockingQueueDemo queueTest = new LinkedBlockingQueueDemo();    // 写入线程    new Thread(new Runnable() {        @Ove
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值