BlockingQueue阻塞队列原理解析

本文深入解析Java中的BlockingQueue阻塞队列,分析其接口定义、主要方法和核心实现,如ArrayBlockingQueue和BlockingDeque。通过源码探讨了阻塞队列在满时如何阻塞线程以及在数据可用时如何唤醒等待线程,揭示了其在并发编程中的重要作用。
摘要由CSDN通过智能技术生成

BlockingQueue,什么鬼,刚开始接触到这个数据结构的时候,从字面意义上根本没看出这个的意思,怎么会有个block冠在前边,感觉是个不太好的词。但是又发现其在某些服务任务框架上经常使用。今天我们来探秘下这个数据结构的用法。

BlockingQueue源码分析

首先,打开JDK的源码,找到BlockingQueue这个数据结构。(android开发要安装的jdk 1.8,在其安装目录即有源码)。

package java.util.concurrent;

import java.util.Collection;
import java.util.Queue;

 * @since 1.5
 * @author Doug Lea
 * @param <E> the type of elements held in this collection
 */
public interface BlockingQueue<E> extends Queue<E> {
   

首先,一个数据结构,包名是java.util.concurrent,很显然,这是java为并发操作设计的数据结构。并且还import了Collection和Queue。 所以其当然也有这两个数据结构的特性。而BlockingQueue是个interface接口类型,那这就不是一个真实的可以对象化的类。如同List 是ArrayList<>()的父类,我们初始化时经常用new ArrayList<>()创建对象并赋值给List<>类型的变量一样。他们都是泛型类,数据类型E可以在使用时具体制定。
接下来我们分析这个接口的主要方法。

/**
     * Inserts the specified element into this queue if it is possible to do
     * so immediately without violating capacity restrictions, returning
     * {@code true} upon success and throwing an
     * {@code IllegalStateException} if no space is currently available.
     * ……
     * /
     boolean add(E e);

从注释看出,add方法可以插入数据到队列中,如果队列满了,则抛出IllegalStateException异常。
之后的方法是offer(E e),其和add方法的不同之处在于,前者在队列满时是异常,后者是返回false,而add只是抛出异常。
而下一个方法,就可以看出BlockingQueue的精髓所在,即阻塞。

   /**
     * Inserts the specified element into this queue, waiting if necessary
     * for space to become available.
     *
     * @param e the element to add
     * @throws InterruptedException if interrupted while waiting
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this queue
     * @throws NullPointerException if the specified element is null
     * @throws IllegalArgumentException if some property of the specified
     *         element prevents it from being added to this queue
     */
    void put(E e) throws InterruptedException;

put的精髓就在于,当队列满的时候,会阻塞住,等有空间时插入。

/**
     * Retrieves and removes the head of this queue, waiting if necessary
     * until an element becomes available.
     *
     * @return the head of this queue
     * @throws InterruptedException if interrupted while waiting
     */
    E take() throws InterruptedException;

反之, 队列的取元素也有阻塞方法,如果队列中有元素,则取出处理,否则队列为空时则阻塞等待。
这里只看了上述方法的注释,其他的都是些辅助方法。
由于BlockingQueue只是个接口,只有定义的方法,但是没有实际的实现,即如何实现阻塞,是在实现类中实现的。

其实现类有ArrayBlockingQueue、BlockingDeque等,详细的如下图所示。
BlockingQueue实现类
ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
DelayQueue:一个使用优先级队列实现的无界阻塞队列。
SynchronousQueue:一个不存储元素的阻塞队列。
LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

我们分别分析ArrayBlockingQueue和BlockingDeque的源码。

ArrayBlockingQueue源码分析

这里不会分析所有的方法,只捡重要的变量和方法进行分析。
首先是类的声明和变量。

public class ArrayBlockingQueue<E> extends AbstractQueue<E>
        implements BlockingQueue<E>, java.io.Serializable {
   
    /** The queued items */
    final Object[] items;

    /** items index for next take, poll, peek or remove */
    int takeIndex;

    /** items index for next put, offer, or add */
    int putIndex;

    /** Number of elements in the queue */
    int count;
    /** Main lock guarding all access */
    final ReentrantLock lock;

    /** Condition for waiting takes */
    private final Condition notEmpty;

    /** Condition for waiting puts */
    private final Condition notFull;

    /**
     * Shared state for currently active iterators, or null if there
     * are known not to be any.  Allows queue operations to update
     * iterator state.
     */
    transient Itrs itrs = null;

其中的items数组,即要添加的队列数据,有取数据的takeIndex和添加数据的putIndex。还有可重入锁lock。
其构造函数显示,队列的长度是外部传入的,即这个类的对象创建的时候,其大小就确定了。同时确定了lock为非公平锁。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值