高并发编程-队列-BlockingQueue-LinkedBlockingQueue

高并发编程-队列-BlockingQueue-LinkedBlockingQueue

一、LinkedBlockingQueue简介

  LinkedBlockingQueue是一个基于链表的阻塞队列,该队列在创建时候,默认大小为Integer.MAX_VALUE,这个数值很大的,所以可以说LinkedBlockingQueue的大小没有限制的,业界有个比较专业的词汇,把它叫做*队列。但是这也带来了一些问题,比如当JVM内存比较小的时候,可能就会出现OOM的情况。所以建议大家在使用的时候根据实际情况设置一个大小。

  LinkedBlockingQueue的内部是单向链表,在链表的内部只能next,也就是说查找元素只能从head查起,从tail插入。

  LinkedBlockingQueue的采用两把锁的分离技术,实现了出队和入队的锁分离,也就是说LinkedBlockingQueue的读写是分离的,提高了它得并发处理能力

二、LinkedBlockingQueue的特点

队列特点:*阻塞队列,可以指定容量,默认为Integer.MAX_VALUE,先进先出
数据结构: 链表结构
锁特点:读写锁分离,操作各自的node对象。takeLock 取node节点保证了顺序不会乱,putlock存数据时保证了有序
条件阻塞:出队时候,如果队列的count=0,证明队列里面没有元素的,notEmpty条件队列会被阻塞。入队时候,如果队列的count=capacity,证明队列已满,这个时候入队线程需要阻塞,notFull需要阻塞。
入队:从tail入队。出队:从head出队

三、LinkedBlockingQueue的简单实用

//创建一个有界队列,这个需要指定大写
BlockingQueue<Integer> linkedBlockingQueue = new LinkedBlockingQueue<>(100)
//默认指定的Queue为*队列
BlockingQueue<Integer> linkedBlockingQueue = new LinkedBlockingQueue<>();

//建议大家在使用的时候指定队列大小,防止出现OOM

四、LinkedBlockingQueue的源码

数据参数

//指定队列容量大小,不指定默认 Integer.MAX_VALUE
private final int capacity;
//统计内部元素数量,这里使用了CAS的原子性操作
private final AtomicInteger count = new AtomicInteger();
//定义链表的头部,初始化时 head=null
transient Node<E> head;
//定义链表的尾部
private transient Node<E> last;
//定义take poll使用的锁,也就是消费者使用的锁
private final ReentrantLock takeLock = new ReentrantLock();
//等待队列的条件队列,当队列无元素时,take锁会阻塞在notEmpty条件上,等待其它线程唤醒
private final Condition notEmpty = takeLock.newCondition();
//定义 put, offer,使用的锁,也就是生产者使用的锁
private final ReentrantLock putLock = new ReentrantLock();
//等待入队的条件队列,当队列满了时,put锁会会阻塞在notFull上,等待其它线程唤醒
private final Condition notFull = putLock.newCondition();


//单链表结构
 static class Node<E> {
        E item;//存储元素

        Node<E> next;//后续节点,单链表结构

        Node(E x) { item = x; }
    }

构造器

//默认的构造器 
public LinkedBlockingQueue() {
// 如果没传容量,就使用最大int值初始化其容量
        this(Integer.MAX_VALUE);
    }

//指定容量大小的构造器
 public LinkedBlockingQueue(int capacity) {
    //如果指定容量大小小于等于0抛出异常
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
//定义初始的head和last节点,初始为空节点
        last = head = new Node<E>(null);
    }

 

上一篇:语法基础:关键字final及static


下一篇:Android ListView功能扩展,实现高性能的瀑布流布局,androidstudio汉化插件