LinkedBlockingQueue是一种阻塞队列,有队列的基本功能,并且带有阻塞的功能,先看下类的继承关系
LinkedBlockingQueue
队列中的每个元素是一个Node,Node有个变量next指向下一个元素,定义如下:
static class Node {
E item;
Node next;
Node(E x) { item = x; }
}
看下怎么入队一个元素put(E e),
1,检查添加的元素是否为空,如果为空,抛出异常
2、创建一个新的Node对象
3、获取一个putLock可中断的锁
4、如果队列已满等待,如果没满就把元素加入队列,把添加前队列数量加1比容量小,唤醒等待的线程
5,释放锁,如果添加元素前队列为空,现在有元素了,唤醒出队等待的线程
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
int c = -1;
Node node = new Node(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
while (count.get() == capacity) {
notFull.await();
}
enqueue(node);
c = count.getAndIncrement();
if (c + 1
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}
下面看看入队的操作enqueue(node),很简单,把node赋值给last的next,并把node 赋值给last。
private void enqueue(Node node) {
last = last.next = node;
}
看下出队的操作take()
1、获取一个takeLock可中断的锁
2、如果队列为空,等待
3、如果不为空,从队列取一个元素
4、如果取出元素后,队列中还有,唤醒等待线程
5、释放锁,如果取出元素前队列是满的,现在取出了一个,队列不是满的了,唤醒入队等待的线程
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();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
现在看看出队的方法dequeue(),把head的next取出来,并且把head指向head的next。
private E dequeue() {
Node h = head;
Node first = h.next;
h.next = h; // help GC
head = first;
E x = first.item;
first.item = null;
return x;
}
领取专属 10元无门槛券
私享最新 技术干货