并发编程之BlockingQueue

一、 简介

BlockingQueue简介

  • 首先它一个队列,所以它继承了Queue接口具有队列的特性;
  • 其次是一个阻塞队列。

我们平时常用的队列只要为一下两种

  • 先进先出-FIFO:先插入的数据最先出队列,类似我们排队买东西,先排队的先买
  • 先进后出-LIFO:后插入的数据最先出队列,类似我们放羽毛球的球筒,先放进去的最后才能拿出来

队列不只有这两种,实现方式不同则会衍生出不同的队列

我们先来看下BlockingQueue的基本数据结构, 如下图

​ 在多线程环境下,我们可以通过BlockingQueue来实现不同线程间的数据共享,比如生产者–消费者模式,我们可以让若干线程生产数据,若干线程消费数据,理想状态下是没有问题的,但是当生产速度大于消费速度导致数据有了一定的积累,或者消费速度大于生产速度导致数据都消费完毕,这种情况下就需要特殊处理下,当数据积累到一定数量时 生产者需要阻塞等待,直到有消费者消费数据,反之亦然。

概括下就是以下两个结论

  • 队列空了:所有的消费线程阻塞等待,直到生产者生产数据放入队列,同时唤醒消费线程
  • 队列满了:所有的生产线程阻塞等待,直到消费者消费了队列中的数据,同时唤醒生产者

当然这些BlockingQueue都已经帮我们做了,我们不需要在关注这些

二、BlockingQueue核心方法

    // 添加指定数据到队尾,成功返回true, 失败抛出IllegalStateException异常	  
		// 底层调用的offer
    boolean add(E e);

		// 添加指定数据到队尾,成功返回true, 失败返回 false  
    boolean offer(E e);

		//  添加指定数据到队尾,如果队列满了,则阻塞当前线程,直到抛出InterruptedException异常
    void put(E e) throws InterruptedException;
		
		// 添加指定数据到队列,如果队列满了则等待指定时间,成功返回true, 失败返回 fals
		// 如果在等待时间内中断了等待线程,则抛出InterruptedExcepution
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;

		// 取出队列的头部的元素,如果没有元素则一直等待直到成功
		// 等到过程中断线程则抛出InterruptedExcepution
    E take() throws InterruptedException;

		// 取出队列的头部的元素,如果没有元素则等待指定时间直到成功,获取不到返回null
		// 等到过程中断线程则抛出InterruptedExcepution
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;

		// 获取当前队列剩余容量
    int remainingCapacity();

		// 删除队列中的元素
    boolean remove(Object o);

		// 是否保存元素
    public boolean contains(Object o);

		// 将队列中全部元素移动到指定集合
    int drainTo(Collection<? super E> c);

		// 将队列中指定数量元素移动到指定集合
    int drainTo(Collection<? super E> c, int maxElements);

​ BlockingQueue和JDK的Queue接口是兼容的,同时在其基础上添加了阻塞的功能。

​ 我们可以看到添加有三个方法,那么它们有什么区别?返回值我们可以看出 **add()offer()**返回的是boolean,put()则无返回值会抛出InterruptedExcepution中断异常,所以add()和offer()是非阻塞的put()是阻塞的

​ 同理,在获取数据的时候我们可以看到take()和poll()也都抛出了InterruptedExcepution中断异常,所以我你推断出这两个方法也是阻塞的。

三、具体实现

刚才我们已经介绍了BlockingQueue的核心方法,下面让我们看下它有哪些常用的具体实现吧

如下图所示,接下来我会一一来介绍他们的特性和具体实现

1、ArrayBlockingQueue

BlockingQueue之ArrayBlockingQueue

2、LinkedBlockingQueue

BlockingQueue之LinkedBlockingQueue

四、比较

ArrayBlockingQueue和LinkedBockingQueue比较

  • 底层数据结构不同:ArrayBlockingQueue底层是循环数组,LinkedBlockingQueue底层是单项链表

  • 初始化方式不同:ArrayBlockingQueue必须制定大小初始化;LinkedBlockingQueue可以不指定容量初始化,默认大小Integer.MAX_VALUE

  • 阻塞方式不同:ArrayBlockingQueue是通用一个全局锁来处理所有操作,入队和出队不能同步;LinkedBlockingQueue队头和队尾分别使用了锁,入队和出队可一同步进行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值