`

Java ArrayBlockingQueue源码解析

阅读更多

转自:http://www.xiaoyaochong.net/wordpress/?p=354

ArrayBlockingQueue是Java并发框架中阻塞队列的最基本的实现,分析这个类就可以知道并发框架中是如何实现阻塞的。

 

笔者工作了一两年之后,还不知道阻塞是如何实现的,当然有一个原因是前期学习的东西比较杂,前后端的东西的懂一点,但是了解的不够深刻,我觉得这是编程学习的禁忌,不管是前端还是后端,在工作3年的时候,你应该有一个方向是拿得出手,见得了人的。

 

转回整体,ArrayBlockingQueue实现阻塞队列的关键在与,对锁(Lock)和等待条件(Condition)的使用的使用,这两个实现的基本功能类似域wait()和notify(),是wait()和notify()的高级用法。

 

本文我们主要分析ArrayBlockingQueue的3个核心方法,put(),take()和poll()。

首先是put()

 

/**
     * 从队列的尾部插入元素,如果队列已满,将阻塞等待到队列有空间的时候进行插入操作。
     *
     */
    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();//释放锁
        }
    }

 这个方法在当前线程没有中断的情况下,获取锁,接着对数组容量进行判断,如果容量已满,则循环等待带容量腾出来为止,最后释放当前线程锁。这样的业务逻辑就产生了这样的场景,线程一进入到该方法,成功插入队列,释放锁,假设刚好容量满;线程二进入该方法,循环等待;线程三从容器中获取元素;线程二判断容量未满,插入,释放锁。如果有多个线程在等待的时候,会出现什么情况呢,从代码的逻辑来看,当多个线程都在阻塞等待的时候,要看谁首先抢到锁,也就是消费方法是抢占式的。

 

 

其次时take()

 

/**
     * 返回队列头部的元素,如果队列为空,阻塞等待其他线程往当前容器放入元素为止。
     */
public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();//  获取当前线程的锁
        try {
            while (count == 0)// 阻塞等待
                notEmpty.await();
            return extract();
        } finally {
            lock.unlock();// 释放锁
        }
    }

这个过程和put()方法类似,这里就不罗嗦了。

 

 

最后poll(),poll有两个重载的方法,有参数和无参数,先讲无参数的。

 

/**
     * 获取队列头部的元素,当队列为空的时候,返回null值
     *
     */
public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();// 锁定
        try {
            return (count == 0) ? null : extract();
        } finally {
            lock.unlock();// 解锁
        }
    }

 这个方法是不阻塞的,当队列未空的时候,直接返回null值,所以实现中只是一个锁的简单使用,防止并发问题。

 

 

poll(...)

/**
     * 获取队列的头部元素,在指定时间之内阻塞等待,如果超出阻塞时间队列仍然空,则返回null值。
     *
     */
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();// 解锁
        }
    }

 这个方法的逻辑和其他方法的不同之处就在Condition的一个时间计数器方法awaitNanos(...),这里先将时间大小根据时间单位换算成纳秒的数值,当队列容量为0是,使用Condition.awaitNanos(...),进行技术,超时后返回空。

 

总之,ArrayBlokingQueue使用的Java的现实锁(Lock)配合Condition进行阻塞,使用Condition进行时间技术。而在并发框架中其他的阻塞和时间技术,也同样是用这两个对象API来实现。

分享到:
评论

相关推荐

    ArrayBlockingQueue源码解析-动力节点共

    总结来说,ArrayBlockingQueue是Java并发编程中一个强大且实用的工具,通过深入理解其源码,我们可以更好地掌握并发控制和队列操作的细节,从而在实际开发中更加高效地利用线程资源。对于并发编程的学习和实践,研究...

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

    本文将深入解析ArrayBlockingQueue的常用方法及其内部实现机制。 ArrayBlockingQueue的核心是一个固定大小的数组`items`,用于存储队列中的元素。此外,它还有3个关键的索引变量:`takeIndex`、`putIndex`和`count`...

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

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

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

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

    java爬虫源码

    Java爬虫源码是用于自动化抓取Web页面信息的程序,通常由一系列的类和方法组成,能够模拟浏览器发送HTTP请求并解析响应的HTML内容。在Java中实现爬虫,多线程技术是非常重要的,因为它可以提高爬虫的运行效率,使...

    线程池管理源码 java 源码

    本文将深入解析线程池的管理源码,帮助读者理解其工作原理和优化策略。 在Java中,`java.util.concurrent`包下的`ThreadPoolExecutor`类是线程池的核心实现。它提供了丰富的参数来定制线程池的行为,包括核心线程数...

    Android面试复习资料大全(包含java源码)

    11. **Java并发集合**:ArrayBlockingQueue、LinkedBlockingQueue、ConcurrentHashMap等线程安全集合的使用和原理。 12. **Java虚拟机(JVM)**:了解JVM的基本概念、对象的创建、内存布局、内存模型、类加载机制、...

    Java线程池,正式上线运行的源码,分享欢迎使用并提意见

    本文将深入探讨Java线程池的原理、使用方式以及其源码解析。 首先,Java线程池主要由`java.util.concurrent.ThreadPoolExecutor`类实现。线程池的核心参数包括核心线程数(corePoolSize)、最大线程数...

    java多线程设计模式详解

    本文将深入探讨几种常见的Java多线程设计模式,并通过源码解析来帮助理解其实现机制。 首先,我们要理解Java多线程的基本概念。在Java中,线程是程序中的执行单元,一个进程可以包含多个线程,它们共享同一块内存...

    JDK1.5线程池源码及详细注释

    new ArrayBlockingQueue(3)); // workQueue for (int i = 0; i ; i++) { final int taskId = i; executor.execute(() -&gt; { System.out.println("Task ID: " + taskId + " started by thread: " + Thread....

    java 线程池源码处理并发

    本文将深入解析Java线程池的源码,探讨其工作原理、核心组件以及如何优化并发性能。 Java线程池的实现主要基于`java.util.concurrent`包中的`ExecutorService`接口,而`ThreadPoolExecutor`类是其具体实现。`...

    精选_毕业设计_基于JAVA的生产者消费者问题_完整源码

    在这个毕业设计中,开发者可能使用了Java的阻塞队列(BlockingQueue)接口,如ArrayBlockingQueue或LinkedBlockingQueue,这些队列内置了线程安全的生产和消费操作,可以有效地实现生产者和消费者之间的同步。...

    java多线程设计模式详解(PDF及源码)

    本资源包含了一个PDF文档和源码,用于详细解析Java中的多线程设计模式。 1. **线程基础** - **创建线程**:Java提供了两种创建线程的方式,即继承Thread类和实现Runnable接口。理解这两种方式的区别和适用场景是...

    Java多线程programmingShiZhanZhiNan(呵心篇).源码

    Java多线程编程实战指南(呵心篇)是一份深入探讨Java并发编程的资源,它提供了丰富的源码示例来帮助开发者理解并掌握多线程技术。在这个领域,Java提供了强大的支持,使得开发者能够构建高性能、高并发的应用程序。...

    java多线程设计模式

    本文将深入探讨Java中的一些重要多线程设计模式,并结合实际案例进行解析。 1. 生产者消费者模式: 生产者消费者模式是一种典型的资源共享问题,通过队列作为缓冲区,生产者线程生产数据并放入队列,消费者线程从...

    java语言模拟多层电梯的实例

    下面将详细解析这个实例中的关键知识点。 首先,我们要理解CS结构,即Client-Server(客户端-服务器)架构。在这个实例中,Java程序可能被分为两个部分:一个是模拟电梯运行的服务器端,负责处理电梯的移动和乘客...

Global site tag (gtag.js) - Google Analytics