jdk源码之LinkedBlckingQueue源码注释

 今天咱们分析一下LinkedBlockingQueue,这是一个咱们使用频率比较高的类。java

public static void main(String[] args) throws Exception {
//咱们这个LinkedBlockingQueue源码分三个关键步骤
//步骤一:先看一个其构造函数,以及核心的属性
    LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
    //步骤二:看一下其关键步骤,插入数据的步骤
queue.put("张三");
//步骤三:看一下其关键步骤,获取数据的步骤
    queue.take();
}

步骤一:

public LinkedBlockingQueue() {
//设置队列的大小
//其实可见,默认状况下是一个无界队列(相似于无界) 
    this(Integer.MAX_VALUE);
}

public LinkedBlockingQueue(int capacity) {
    if (capacity <= 0) throw new IllegalArgumentException();
//设置队列大小
    this.capacity = capacity;
//初始化一个空节点
    last = head = new Node<E>(null);
}


//获取数据的时候的一把锁
//由于是队列,这把锁在队尾
private final ReentrantLock takeLock = new ReentrantLock();

//关于takeLock的对象
private final Condition notEmpty = takeLock.newCondition();

//put数据的时候的一把锁
//由于是队列,因此这把锁在队头
private final ReentrantLock putLock = new ReentrantLock();
//关于putLock的对象
private final Condition notFull = putLock.newCondition();

其实LinkedBlockingQueue的设计也是很巧妙的,使用了两把锁去控制。两把锁之间互相不影响。大幅提高了并发的性能。
接下来自咱们分析一下步骤二:

public void put(E e) throws InterruptedException {
    if (e == null) throw new NullPointerException();
    // Note: convention in all put/take/etc is to preset local var
    // holding count negative to indicate failure unless set.
    int c = -1;
//根据当前传入的元素封装节点
    Node<E> node = new Node<E>(e);
//获取putLocak锁
    final ReentrantLock putLock = this.putLock;
//统计当前元数据个数
    final AtomicInteger count = this.count;
//加锁
    putLock.lockInterruptibly();
    try {
//若是队列存满了,那就等待
        while (count.get() == capacity) {
            notFull.await();
        }
//入队,这个操做其实也很简单
// last = last.next = node;
        enqueue(node);
//入队完了之后递增当前 元素个数
//不过咱们须要知道的是,好比当前的元素个数
//已是9递增到10了。
//这个时候count=10  c=9
        c = count.getAndIncrement();
//若是c+1小于总的容量,说明队列至少有一个空间是能够存数据的。
        if (c + 1 < capacity)
//唤醒以前由于队列满了而处于等待的锁。
            notFull.signal();
    } finally {
//释放锁
        putLock.unlock();
    }
//若是c==0,说明当前的队列里面确定还有元素,能够获取
    if (c == 0)
//唤醒以前由于队列为空而处于等待的锁
        signalNotEmpty();
}


咱们发现其实LinkedBlockingQueue的源码阅读下来难度不大。
public E take() throws InterruptedException {
    E x;
    int c = -1;
//获取当前元素个数
    final AtomicInteger count = this.count;
//获取takeLock锁
    final ReentrantLock takeLock = this.takeLock;
//获取元素的时候加锁
    takeLock.lockInterruptibly();
    try {
//若是当前元素等于0,说明没有元素了
        while (count.get() == 0) {
//若是队列为空,那么就等待
            notEmpty.await();
        }
//出队,获取元素
//出队的代码也是极其简单就是变化一下指针就能够。
        x = dequeue();
//递减元素
//加入当前count 由10 变成了9
//count =10  count=9
        c = count.getAndDecrement();
//说明队列不为空
        if (c > 1)
//不为空,那么就唤醒 可能由于队列为空而处于等待的锁
            notEmpty.signal();
    } finally {
//释放锁
        takeLock.unlock();
    }
//若是c==capacity说明队列里面确定会有不满的元素
    if (c == capacity)
//唤醒,由于队列满了而处于等待的锁。
        signalNotFull();
//返回当前元素
    return x;
}

   若是有了以前的基础,阅读这段代码应该是比较简单的。node

   搞定,手工!并发

相关文章
相关标签/搜索