进来学习 BlockingQueue 阻塞队列

 阻塞队列家族:

一、ArrayBlockingQueue

用数组实现的有界队列。此队列按照先进先出(FIFO)的原则对元素进行排序。ArrayBlockingQueue 一旦创建,容量不能改变。其并发控制采用可重入锁来控制,不管是插入操作还是读取操作,都需要获取到锁才能进行操作。当队列容量满时,尝试将元素放入队列将导致操作阻塞;尝试从一个空队列中取一个元素也会同样阻塞。

默认情况下不保证线程访问队列的公平性。所谓公平性是指严格按照线程等待的绝对时间顺序,即最先等待的线程能够最先访问到 ArrayBlockingQueue。而非公平性则是指访问 ArrayBlockingQueu 的顺序不是严格的时间顺序,有可能存在,当 ArrayBlockingQueue 可以被访问时,长时间阻塞的线程依然无法访问到 ArrayBlockingQueue。如果保证公平性,通常会降低吞吐量。如果需要获取公平性的 ArrayBlockingQueue,我们可以使用以下代码创建:

 ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(10,true);

访问的公平性是使用可重入锁 ReentrantLock 实现的:

    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        this.items = new Object[capacity];
        lock = new ReentrantLock(fair);
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }

二、LinkedBlockingQueue

底层基于单向链表实现的阻塞队列。可以当做无界队列也可以当做有界队列来使用,同样满足FIFO 的特性,与 ArrayBlockingQueue 相比起来具有更高的吞吐量,为了防止LinkedBlockingQueue 容量迅速增加,损耗大量内存,通常在创建 LinkedBlockingQueue 对象时,会指定其大小,如果未指定,容量等于 Integer.MAX_VALUE。

三、SynchronousQueue

是一个不存储元素的阻塞队列。每一个put操作必须等待一个 take 操作,否则不能继续添加元素。 SynchronousQueue 可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线程。队列本身不存储任何元素,非常适合于传递性场景。SynchronousQueue 的吞吐量高于ArrayBlockingQueue 和 LinkedBlockingQueue。

四、LinkedTransferQueue

是一个由链表结构组成的无界阻塞 TransferQueue 队列。相对于其他阻塞队列, LinkedTransferQueue 多了 tryTransfer 和 transfer 方法。

1.tryTransfer 方法:用来试探生产者传入的元素是否能直接传给消费者。如果没有消费者等待接收元素,则返回false。和 transfer 方法的区别是 tryTransfer  方法无论消费者是否接收元素,方法立即返回。而 transfer 方法是必须等到消费者消费了才返回。

2.transfer 方法:如果当前有消费者正在等待接收元素(消费者使用 take() 方法或带时间限制的 poll()方法时,transfer 方法可以把生产者传入的元素立刻 transfer(传输)给消费者。如果没有消费者在等待接收元素, transfer 方法会将元素存放在队列的 tail 节点,并等到该元素被消费者消费了才返回)。

五、PriorityBlockingQueue

支持优先级的无界阻塞队列。默认情况下元素采用自然顺序进行排序,也可以通过自定义类实现compareTo() 方法来指定元素排序规则,或者初始化是通过构造器参数 Comparator 来指定排序规则。PriorityBlockingQueue 并发控制采用的是 ReentrantLock 。

六、LinkedBlockingDeque

是一个由链表结构组成的双向阻塞队列。所谓双向队列指的是你可以从队列的两端插入和移动元素。双端队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。相比其他的阻塞队列,LinkedBlockingDeque 多了 addFirst, addLast, offerFirst, offerLast, peekFirst, peekLast等方法。以 First 单词结尾的方法,表示插入,获取(peek)或移除双端队列的第一个元素。以 Last 单词结尾的方法, 表示插入,获取或移除双端队列的最后一个元素。另外插入方法add 等同于 addLast, 移除方法 remove 等效于 removeFirst。

七、DelayQueue

是一个支持延时获取元素的无界阻塞队列。队列使用 PriorityQueue 来实现。队列中的元素必须实现 Delayed 接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。我们可以 将 DelayQueue 运用在以下应用场景:

1. 缓存系统设计:可以用 DelayQueue  保存缓存元素的有效期,使用一个线程循环查询 DelayQueue,一旦能从 DelayQueue 中获取元素时,表示缓存有效期到了。

2.定时任务调度: 使用 DelayQueue 保存当天将会执行的任务和执行时间,一旦从 DelayQueue 中获取到任务就开始执行。比如 TimerQueue 就是使用 DelayQueue 实现的。


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值