• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > Java中的常用阻塞队列源码分析

Java中的常用阻塞队列源码分析

作者:路漫漫,水迢迢 字体:[增加 减小] 来源:互联网 时间:2017-07-22

路漫漫,水迢迢通过本文主要向大家介绍了java,阻塞队列,原理等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

定义

支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满。支持阻塞的移除方法:意思是在队列为空时,获取元素的线程会等待队列变为非空。
阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。阻塞队列就是生产者用来存放元素、消费者用来获取元素的容器。

ArrayBlockingQueue

由数组组成的无界阻塞队列。
一个建立在数组之上被BlockingQueue绑定的阻塞队列。这个队列元素顺序是先进先出。队列的头部是在队列中待的时间最长的元素。队列的尾部是再队列中待的时间最短的元素。新的元素会被插入到队列尾部,并且队列从队列头部获取元素。这是一个典型的绑定缓冲,在这个缓冲区中,有一个固定大小的数组持有生产者插入的数据,并且消费者会提取这些数据。一旦这个类被创建,那么这个数组的容量将不能再被改变。尝试使用put操作给一个满队列插入元素将导致这个操作被阻塞;尝试从空队列中取元素也会被阻塞。
这个类推荐了一个可选的公平策略来排序等待的生产者和消费者线程。默认的,这个顺序是不确定的。但是队列会使用公平的设置true来使线程按照先进先出顺序访问。通常公平性会减少吞吐量但是却减少了可变性以及避免了线程饥饿。

ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(1000,true);

源码分析

 /**
     *capacity指定队列的大小
     *fair指定是否公平
     */
    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        this.items = new Object[capacity];
        lock = new ReentrantLock(fair);
        // 这两个notEmpty和notFull参数实际上是Condition,而Condition可以把它看做一个阻塞信号
        // Condition的子类ConditionObject(是AbstractQueuedSynchronizer的内部类)拥有两个方法signal和
        // signalAll方法,前一个方法是唤醒队列中得第一个线程,而signalAll是唤醒队列中得所有等待线程,
        // 但是只有一个等待的线程会被选择,这两个方法可以看做notify和notifyAll的变体。
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }

在这个阻塞队列的insert和remove方法中都会被调用signal来唤醒等待线程,在put方法中,如果队列已经满了,则会调用await方法来,直到队列有空位,才会调用insert方法插入元素。源代码如下:

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

    private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);
        ++count;
        notEmpty.signal();
    }

如果不想在队列满了之后,再插入元素被阻塞,提供了offer方法,这个offer方法有重载方法,调用offer(E e)方法时,如果队列已经满了,那么会直接返回一个false,如果没有满,则直接调用insert插入到队列中;调用offer(E e, long timeout, TimeUnit unit)方法时,会在队列满了之后阻塞队列,但是这里可以由开发人员设置超时时间,如果超时时队列还是满的,则会以false返回。源码如下所示

public boolean offer(E e, long timeout, TimeUnit unit)
    throws InterruptedException {
    checkNotNull(e);
    long nanos = unit.toNanos(timeout);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == items.length) {
        if (nanos <= 0)
            return false;
        nanos = notFull.awaitNanos(nanos);
        }
        insert(e);
        return true;
    } finally {
        lock.unlock();
    }
    }
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();
        }
    }

插入数据有阻塞和非阻塞之分,那么提取数据也肯定就有阻塞与非阻塞之分了。
其中take方法是个阻塞方法,当队列为空时,就被阻塞,源码如下:

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

方法poll是重载方法,跟offer相对,也有基础方法和超时方法之分。
在这个类中还提供了peek方法来提取数据,但是peek方法是从对了的tail提取,而pool是从队列的head提取,即peek提取的元素是进入队列最晚的,而pool提取的元素是进入队列最早时间最长的元素。下面看看pool的源码

  public E poll() {
        final ReentrantLock lock = this.
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • JavaThreadPoolExecutor线程池调度器
  • 全面掌握Java内部类
  • Java中的常用阻塞队列源码分析
  • Java虚拟机(四)垃圾收集算法
  • Java内存模型与线程
  • Java中如何优雅正确的终止线程
  • [译]深入字节码操作:使用ASM和Javassist创建审核日志
  • IntelliJIDEA平台下JNI编程(五)—本地C代码创建Java对象及引用
  • 【java总结】设计模式详解
  • Java代码中常见技术债务处理之Exception

相关文章

  • 2017-05-28Java多线程并发编程 Volatile关键字
  • 2017-05-28JFileChooser实现对选定文件夹内图片自动播放和暂停播放实例代码
  • 2017-05-28Kotlin 基础语法详细介绍
  • 2017-05-28详解spring封装hbase的代码实现
  • 2017-05-28Struts2 文件上传进度条的实现实例代码
  • 2017-05-28Servlet的5种方式实现表单提交(注册小功能),后台获取表单数据实例
  • 2017-05-28浅谈Java中几个常用集合添加元素的效率
  • 2017-05-28配置Spring4.0注解Cache+Redis缓存的用法
  • 2017-05-28Java实现读取文章中重复出现的中文字符串
  • 2017-05-28Java微信公众平台开发(1) 接入微信公众平台

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Java 加密解密基础分类及模式归纳整理
    • Java中的super关键字_动力节点Java学院整理
    • 面向对象和面向过程的区别(动力节点java学院整理)
    • Java Socket编程(三) 服务器Sockets
    • http协议进阶之Transfer-Encoding和HttpCore实现详解
    • 老生常谈java垃圾回收算法(必看篇)
    • Java经典排序算法之希尔排序详解
    • ByteArrayInputStream简介和使用_动力节点Java学院整理
    • SWT(JFace)小制作 FileBrowser文件浏览
    • 解决Java原生压缩组件不支持中文文件名乱码的问题

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有