BlockingQueue

1 篇文章 0 订阅

BlockingQueue

BlockingQueue其实就是阻塞队列,是基于阻塞机制实现的线程安全的队列。而阻塞机制的实现是通过在入队和出队时加锁的方式避免并发操作。
BlockingQueue不同于普通的Queue的区别主要是:
1.通过在入队和出队时进行加锁,保证了队列线程安全
2.支持阻塞的入队和出队方法:当队列满时,会阻塞入队的线程,直到队列不满;当队列为空时,会阻塞出队的线程,直到队列中有元素。
BlockingQueue常用于生产者-消费者模型中,往队列里添加元素的是生产者,从队列中获取元素的是消费者;通常情况下生产者和消费者都是由多个线程组成;下图所示则为一个最常见的生产者-消费者模型,生产者和消费者之间通过队列平衡两者的的处理能力、进行解耦等。
在这里插入图片描述

BlockingQueue接口定义

BlockingQueue继承了Queue接口,在Queue接口基础上,又提供了若干其他方法,其定义源码如下:

public interface BlockingQueue<E> extends Queue<E> {
    /**
     * 入队一个元素,如果有空间则直接插入,并返回true;
     * 如果没有空间则抛出IllegalStateException
     */
    boolean add(E e);

    /**
     * 入队一个元素,如果有空间则直接插入,并返回true;
     * 如果没有空间返回false
     */
    boolean offer(E e);

    /**
     * 入队一个元素,如果有空间则直接插入,如果没有空间则一直阻塞等待
     */
    void put(E e) throws InterruptedException;

    /**
     * 入队一个元素,如果有空间则直接插入,并返回true;
     * 如果没有空间则等待timeout时间,插入失败则返回false
     */
    boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * 出队一个元素,如果存在则直接出队,如果没有空间则一直阻塞等待
     */
    E take() throws InterruptedException;

    /**
     * 出队一个元素,如果存在则直接出队,如果没有空间则等待timeout时间,无元素则返回null
     */
    E poll(long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * 返回该队列剩余的容量(如果没有限制则返回Integer.MAX_VALUE)
     */
    int remainingCapacity();

    /**
     * 如果元素o在队列中存在,则从队列中删除
     */
    boolean remove(Object o);

    /**
     * 判断队列中是否存在元素o
     */
    public boolean contains(Object o);

    /**
     * 将队列中的所有元素出队,并添加到给定的集合c中,返回出队的元素数量
     */
    int drainTo(Collection<? super E> c);

    /**
     * 将队列中的元素出队,限制数量maxElements个,并添加到给定的集合c中,返回出队的元素数量
     */
    int drainTo(Collection<? super E> c, int maxElements);
}

BlockingQueue主要提供了四类方法,如下表所示:
在这里插入图片描述
除了抛出异常和返回特定值方法与Queue接口定义相同外,BlockingQueue还提供了两类阻塞方法:一种是当队列没有空间/元素时一直阻塞,直到有空间/有元素;另一种是在特定的时间尝试入队/出队,等待时间可以自定义。
在本文开始我们了解到,BlockingQueue是线程安全的队列,所以提供的方法也都是线程安全的;那么下面我们就继续看下BlockingQueue的实现类,以及如何实现线程安全和阻塞。

BlockingQueue实现类及原理

主要实现类在这里插入图片描述
其中在日常开发中用的比较多的是ArrayBlockingQueue和LinkedBlockingQueue,本文也将主要介绍这两个实现类的原理。
ArrayBlockingQueue是基于数组实现的阻塞队列,下面我们看下它的主要用法。
ArrayBlockingQueue的用法:

public void testArrayBlockingQueue() throws InterruptedException {
  // 创建ArrayBlockingQueue实例,设置队列大小为10
  BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
  boolean r1 = queue.add(1);          // 使用add方法入队元素,如果无空间则抛出异常
  boolean r2 = queue.offer(2);     		// 使用offer方法入队元素
  queue.put(3);                    		// 使用put方法入队元素;如果无空间则会一直阻塞
  boolean r3 = queue.offer(4, 30, TimeUnit.SECONDS); 	// 使用offer方法入队元素;如果无空间则会等待30s

  Integer o1 = queue.remove();        // 使用remove方法出队元素,如果无元素则抛出异常
  Integer o2 = queue.poll();          // 使用poll方法出队元素 
  Integer o3 = queue.take();          // 使用take方法出队元素;如果无元素则一直阻塞
  Integer o4 = queue.poll(10, TimeUnit.SECONDS);       // 使用poll方法出队元素; 如果无空间则等待10s
}

ArrayBlockingQueue的原理

https://juejin.cn/post/6999798721269465102

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值