Java并发包源码学习:阻塞队列实现之LBQ源码解析,负载均衡nginx面试

private final int capacity;

/** 原子变量,记录元素个数 */

private final AtomicInteger count = new AtomicInteger();

/**

  • 哨兵头节点,head.next才是队列的第一个元素

*/

transient Node head;

/**

  • 指向最后一个元素

*/

private transient Node last;

/** 用来控制同时只有一个线程可以从队头获取元素 */

private final ReentrantLock takeLock = new ReentrantLock();

/** 条件队列,队列为空时,执行出队take操作的线程将会被置入该条件队列 */

private final Condition notEmpty = takeLock.newCondition();

/** 用来控制同时只有一个线程可以从队尾插入元素 */

private final ReentrantLock putLock = new ReentrantLock();

/** 条件队列,队列满时,执行入队操作put的线程将会被置入该条件队列 */

private final Condition notFull = putLock.newCondition();

}

  • 单向链表实现,维护head和last两个Node节点,head是哨兵节点,head.next是第一个真正的元素,last指向队尾节点。

  • 队列中的元素通过AtomicInteger类型的原子变量count记录。

  • 维护两把锁:takeLock保证同时只有一个线程可以从对头获取元素,putLock保证只有一个线程可以在队尾插入元素。

  • 维护两个条件变量:notEmpty和notFull,维护条件队列,用以存放入队出队阻塞的线程。

如果希望获取一个元素,需要先获取takeLock锁,且notEmpty条件成立。 如果希望插入一个元素,需要先获取putLock锁,且notFull条件成立。

构造器

===

使用LinkedBlockingQueue的时候,可以指定容量,也可以使用默认的Integer.MAX_VALUE,几乎就是无界的了,当然,也可以传入集合对象,直接构造。

// 如果不指定容量,默认容量为Integer.MAX_VALUE (1 << 30) - 1

public LinkedBlockingQueue() {

this(Integer.MAX_VALUE);

}

// 传入指定的容量

public LinkedBlockingQueue(int capacity) {

if (capacity <= 0) throw new IllegalArgumentException();

this.capacity = capacity;

// 初始化last 和 head指针

last = head = new Node(null);

}

// 传入指定集合对象,容量视为Integer.MAX_VALUE,直接构造queue

public LinkedBlockingQueue(Collection c) {

this(Integer.MAX_VALUE);

你可能感兴趣的:(程序员,面试,java,后端)