`

ArrayBlockingQueue 源码赏析

阅读更多

 

ArrayBlockingQueue为BlockingQueue的实现类,常用的阻塞队列,先来看一下次类的成员变量:

 

    /** 存放数据的数组*/
    final Object[] items;

    /**队列出口数据在数组中的下标*/
    int takeIndex;

    /**队列入口在数组中的下标*/
    int putIndex;

    /**存放数据数组的实际长度(被存放了数据的长度)*/
    int count;

    /**并发用到的locak*/
    final ReentrantLock lock;

    /**可以从队列里取出数据的条件变量*/
    private final Condition notEmpty;

    /**向队列输入数据的条件变量*/
    private final Condition notFull;

 

 根据上面代码中的注释,大家应该知道成员变量的作用

 

下面我们来看几个常用的方法的源码:

1 构造方法:

    public ArrayBlockingQueue(int capacity, boolean fair,
                              Collection<? extends E> c) {
        this(capacity, fair);

        final ReentrantLock lock = this.lock;
        lock.lock(); // Lock only for visibility, not mutual exclusion
        try {
            int i = 0;
            try {
                for (E e : c) {
                    checkNotNull(e);
                    items[i++] = e;
                }
            } catch (ArrayIndexOutOfBoundsException ex) {
                throw new IllegalArgumentException();
            }
            count = i;
            putIndex = (i == capacity) ? 0 : i;
        } finally {
            lock.unlock();
        }
    }

    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();
    }

   由此构造方法来看,在创建ArrayBlockingQueue对象时,可以指定阻塞队列的长度,Lock的类型(公平锁或是非公平锁),以及向队列初始化一些数据,加入数据的时候要加锁!在finally语句块里释放锁

 

2 向队列添加元素 add  offer  put

    public boolean add(E e) {
        return super.add(e);
    }


    public boolean offer(E e) {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                insert(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }


    public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            insert(e);
        } finally {
            lock.unlock();
        }
    }

 add 方法的具体实现在父类中:

   

    public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }

  可以看到add的具体实现调用的是offer方法,如果队列已满,则会抛出IllegalStateException异常

 

  在offer方法中,如果队列已满,则返回false(添加过程使用Lock,保证线程安全)

 

  在put方法中,如果队列已满,条件变量notFull调用await方法,使其他向队列插入数据的线程阻塞

 

3 从队列取出元素 take poll peek

   

   public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return extract();
        } finally {
            lock.unlock();
        }
    }

    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0) {
                if (nanos <= 0)
                    return null;
                nanos = notEmpty.awaitNanos(nanos);
            }
            return extract();
        } finally {
            lock.unlock();
        }
    }

    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : itemAt(takeIndex);
        } finally {
            lock.unlock();
        }
    }

 

   take 从阻塞队列里去取数据,整个过程加入中断锁,当队列中的数据为空时,notEmpty条件变量阻塞队列上的取数据的线程

 

   poll 整个取数据的过程加锁, 支持设置等待时间

 

   peek 此方法并不是取数据,而是读取数据,把队列出口处的数据返回,队列长度并没有减小,整个过程中加锁!

 

把ArrayBlockingQueue源码拿出来分析一下的原因是:阻塞队列实现线程阻塞和安全是由Condition和Lock一起来实现的,所以要深入掌握Lock和Condition的使用!

 

 

分享到:
评论

相关推荐

    ArrayBlockingQueue源码分析.docx

    下面我们将深入分析其主要的实现机制、方法以及源码。 1. **数据结构与容量** `ArrayBlockingQueue` 内部使用一个数组 `items` 来存储元素,因此它的容量在创建时就需要指定,且不可改变。这个容量限制确保了队列...

    ArrayBlockingQueue源码解析-动力节点共

    在深入理解ArrayBlockingQueue的源码之前,我们需要先了解其基本概念和特性。 ArrayBlockingQueue的核心特点在于其固定大小的容量,这使得它在处理高并发场景时能有效控制资源消耗。队列的元素按照FIFO(先进先出)...

    Java源码解析阻塞队列ArrayBlockingQueue介绍

    Java源码解析阻塞队列ArrayBlockingQueue介绍 Java源码解析阻塞队列ArrayBlockingQueue介绍是Java中的一种阻塞队列实现,使用ReentrantLock和Condition来实现同步和阻塞机制。本文将对ArrayBlockingQueue的源码进行...

    Java源码解析阻塞队列ArrayBlockingQueue常用方法

    Java中的ArrayBlockingQueue是一个高效的并发数据结构,它是Java并发包`java.util.concurrent`下的一个阻塞队列。本文将深入解析ArrayBlockingQueue的常用方法及其内部实现机制。 ArrayBlockingQueue的核心是一个...

    【死磕Java集合】-集合源码分析.pdf

    八、ArrayBlockingQueue源码分析 ArrayBlockingQueue是一种基于数组实现的阻塞队列,提供了线程安全的生产者消费者模型。ArrayBlockingQueue的继承体系中,它继承了AbstractQueue,实现了BlockingQueue接口。 ...

    Java源码解析阻塞队列ArrayBlockingQueue功能简介

    Java源码解析阻塞队列ArrayBlockingQueue功能简介 ArrayBlockingQueue是Java中一个重要的阻塞队列实现,它基于数组实现了有界阻塞队列,提供FIFO(First-In-First-Out)功能。该队列的头元素是最长时间呆在队列中的...

    详细分析Java并发集合ArrayBlockingQueue的用法

    Java并发集合ArrayBlockingQueue的用法详解 Java并发集合ArrayBlockingQueue是Java并发集合框架下的一个重要组件,它提供了阻塞队列的实现,用于多线程环境下的并发操作。下面是对ArrayBlockingQueue的用法详解: ...

    并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解

    "并发容器之ArrayBlockingQueue和LinkedBlockingQueue实现原理详解" ArrayBlockingQueue和LinkedBlockingQueue是Java并发容器中两个常用的阻塞队列实现,分别基于数组和链表存储元素。它们都继承自AbstractQueue类...

    线程池管理源码 java 源码

    常见的有无界队列(如ArrayBlockingQueue)和有界队列(如LinkedBlockingQueue),以及优先级队列(PriorityBlockingQueue)。队列的选择直接影响线程池的处理策略。 `ThreadPoolExecutor`的工作流程如下: 1. **...

    java并发之ArrayBlockingQueue详细介绍

    Java并发之ArrayBlockingQueue详细介绍 ArrayBlockingQueue是Java并发编程中常用的线程安全队列,经常被用作任务队列在线程池中。它是基于数组实现的循环队列,具有线程安全的实现。 ArrayBlockingQueue的实现 ...

    免费开源-【Java学习+面试指南】部分内容大部分是Java程序员所需要掌握的核心知识

    ArrayList核心源码+扩容机制分析LinkedList核心源码分析HashMap核心源码+底层数据结构分析ConcurrentHashMap核心源码+底层数据结构分析LinkedHashMap核心源码分析CopyOnWriteArrayList核心源码分析...

    Java concurrency集合之ArrayBlockingQueue_动力节点Java学院整理

    ArrayBlockingQueue是Java并发编程中一个重要的集合类,它属于 BlockingQueue 接口的一个实现,主要特点是线程安全、有界以及基于数组的阻塞队列。线程安全得益于其内部使用了Java并发包中的ReentrantLock(可重入锁...

    26不让我进门,我就在门口一直等!—BlockingQueue和ArrayBlockingQueue.pdf

    —BlockingQueue和ArrayBlockingQueue.pdf” 【描述】:此文档是关于Java并发编程的学习资料,以漫画形式讲解,聚焦于Java并发编程中的核心概念——BlockingQueue接口及其具体实现ArrayBlockingQueue。 【标签】:...

    java中LinkedBlockingQueue与ArrayBlockingQueue的异同

    Java中的`LinkedBlockingQueue`和`ArrayBlockingQueue`都是`java.util.concurrent`包下的线程安全队列,它们都实现了`BlockingQueue`接口,提供了一种高效、线程安全的数据同步方式。这两种队列在很多方面都有相似之...

    Java高并发核心编程(卷2)源码

    4. **并发容器**:如`ConcurrentHashMap`、`BlockingQueue`、`ArrayBlockingQueue`、`LinkedBlockingQueue`等,这些容器在并发环境下提供高效的数据共享。源码分析可以帮助理解它们如何保证线程安全和并发性能。 5....

    Java并发包源码分析(JDK1.8)

    囊括了java.util.concurrent包中大部分类的源码分析,其中涉及automic包,locks包(AbstractQueuedSynchronizer、ReentrantLock、ReentrantReadWriteLock、LockSupport等),queue(ArrayBlockingQueue、...

    java concurrent 精简源码

    Java并发库中实现阻塞队列的主要类有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue和DelayQueue等。它们在并发编程中起到缓冲和协调生产者与消费者线程的作用,实现高效的数据交换。 3. **线程...

    JAVA经典线程池源码

    通过深入研究和使用本资源提供的"JAVA经典线程池源码",开发者不仅可以理解线程池的基本工作原理,还能学习到如何自定义线程池以适应特定场景,从而提高程序的并发性能和稳定性。在实际项目中,结合Java并发API的...

Global site tag (gtag.js) - Google Analytics