LinkedBlockingQueue源码解析

335 阅读3分钟

LinkedBlockingQueue

Attributes

  • capacity:队列容量,可通过构造方法传入,否则为Integer.MAX_VALUE
  • count:当前元素数目,AtomicInteger类型
  • head:队列头,特征:head.item == null
  • last:队列尾,特征:last.next == null
  • takeLock:取操作的锁(ReentrantLock)
  • notEmpty:取操作锁拿到的condition
  • putLock:存放操作的锁(ReentrantLock)
  • notFull:存放操作锁拿到的condition

Construction Method

  • LinkedBlockingQueue():初始化默认队列容量为Integer.MAX_VALUE的LinkedBlockingQueue
  • LinkedBlockingQueue(capacity):初始化指定队列容量的LinkedBlockingQueue,并且设定head和last为item值为null的node

Method

put()

特征:往队列put值时,如果队列满了就一直等待

public void put(E e) throws InterruptedException {
    if (e == null) throw new NullPointerException();
    int c = -1;
    Node<E> node = new Node<E>(e);
    final ReentrantLock putLock = this.putLock;
    final AtomicInteger count = this.count;
    putLock.lockInterruptibly();
    try {
        /*
         * 如果队列满了,就等待,直到队列有空闲才会被唤醒
         */
        while (count.get() == capacity) {
            notFull.await();
        }
        // 放入队尾
        enqueue(node);
        // 计数原子的加1
        c = count.getAndIncrement();
        // 加完之后如果队列有空闲,就唤醒等待往队列放值的线程
        if (c + 1 < capacity)
            notFull.signal();
    } finally {
        putLock.unlock();
    }
    // 表示此次put值之前队列是空的,现在队列有值了,就去唤醒取值的线程
    if (c == 0)
        signalNotEmpty();
}

offer(timeout)

特征:往队列put值时,如果队列满了就等待timeout时间长度,如果还满就直接返回false

public boolean offer(E e, long timeout, TimeUnit unit)
    throws InterruptedException {

    if (e == null) throw new NullPointerException();
    long nanos = unit.toNanos(timeout);
    int c = -1;
    final ReentrantLock putLock = this.putLock;
    final AtomicInteger count = this.count;
    putLock.lockInterruptibly();
    try {
        // 队列满了的情况下,等待timeout的时间,如果超过这个时间就返回false
        while (count.get() == capacity) {
            if (nanos <= 0)
                return false;
            nanos = notFull.awaitNanos(nanos);
        }
        enqueue(new Node<E>(e));
        c = count.getAndIncrement();
        if (c + 1 < capacity)
            notFull.signal();
    } finally {
        putLock.unlock();
    }
    // 表示此次offer值之前队列是空的,现在队列有值了,就去唤醒取值的线程
    if (c == 0)
        signalNotEmpty();
    return true;
}

offer()

特征:往队列put值时,如果队列满了就直接返回false

public boolean offer(E e) {
    if (e == null) throw new NullPointerException();
    final AtomicInteger count = this.count;
    // 如果队列满了,立即返回false
    if (count.get() == capacity)
        return false;
    int c = -1;
    Node<E> node = new Node<E>(e);
    final ReentrantLock putLock = this.putLock;
    putLock.lock();
    try {
        if (count.get() < capacity) {
            enqueue(node);
            c = count.getAndIncrement();
            if (c + 1 < capacity)
                notFull.signal();
        }
    } finally {
        putLock.unlock();
    }
    if (c == 0)
        signalNotEmpty();
    // 返回是否offer成功
    return c >= 0;
}

take()

public E take() throws InterruptedException {
    E x;
    int c = -1;
    final AtomicInteger count = this.count;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lockInterruptibly();
    try {
        // 如果队列空了,等待直到被唤醒
        while (count.get() == 0) {
            notEmpty.await();
        }
        // 取出head.next的item值
        x = dequeue();
        // 技术值原子的减一
        c = count.getAndDecrement();
        // take完后如果队列不为空,则唤醒等待take的队列
        if (c > 1)
            notEmpty.signal();
    } finally {
        takeLock.unlock();
    }
    // 如果take之前队列是满的,则take完后唤醒往队列放值的线程
    if (c == capacity)
        signalNotFull();
    return x;
}

poll(timeout)

public E poll(long timeout, TimeUnit unit) throws InterruptedException {
    E x = null;
    int c = -1;
    long nanos = unit.toNanos(timeout);
    final AtomicInteger count = this.count;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lockInterruptibly();
    try {
        // 队列空的时候等待timeout时间后返回值
        while (count.get() == 0) {
            if (nanos <= 0)
                return null;
            nanos = notEmpty.awaitNanos(nanos);
        }
        x = dequeue();
        c = count.getAndDecrement();
        if (c > 1)
            notEmpty.signal();
    } finally {
        takeLock.unlock();
    }
    if (c == capacity)
        signalNotFull();
    return x;

poll()

public E poll() {
    final AtomicInteger count = this.count;
    // 队列空的时候立即返回null
    if (count.get() == 0)
        return null;
    E x = null;
    int c = -1;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lock();
    try {
        if (count.get() > 0) {
            x = dequeue();
            c = count.getAndDecrement();
            if (c > 1)
                notEmpty.signal();
        }
    } finally {
        takeLock.unlock();
    }
    if (c == capacity)
        signalNotFull();
    return x;
}

Inner Class

Node

  • item:value值
    next: 下一个node