源码角度了解阻塞队列之LinkedBlockingQueue
【摘要】 源码角度了解阻塞队列之LinkedBlockingQueueLinkedBlockingQueue是单向链表的阻塞队列,通过它的构造方法可以知道如果不指定容量的话,这个队列的长度Integer类型的最大值,它有两个锁和两个Condition,notEmpty = takeLock.newCondition();这是正在等待获取元素的等待队列,notFull = putLock.newCon...
源码角度了解阻塞队列之LinkedBlockingQueue
LinkedBlockingQueue是单向链表的阻塞队列,通过它的构造方法可以知道如果不指定容量的话,这个队列的长度Integer类型的最大值,它有两个锁和两个Condition,notEmpty = takeLock.newCondition();这是正在等待获取元素的等待队列,notFull = putLock.newCondition();这是正在等待放入元素的等待队列
count是AtomicInteger对象,保证原子性,因为put()方法和take()都会操作这个变量,需要保证原子性
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);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}
- 加可中断锁
- 获取所有的元素个数
- 如果元素个数和总的容量相等的话,阻塞等待
- 没有达到最大容量数调用enqueue()方法将元素添加到阻塞队列中
- count值加1,这里getAndIncrement()返回的是旧值,然后再进行加一操作,如果得到值小于容量的话说明队列中还可以放入元素,唤醒notFull的线程
- 解锁
- 如果入队前为0,也就是入队后队列不为空了,就可以唤醒notEmpty的线程来取队列中的元素,signalNotEmpty()方法中需要获取takeLock锁才能调用notEmpty.signal()唤醒线程
take()方法
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();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
- 加可中断锁
- 获取所有的元素个数
- 如果为0的话,阻塞等待
- 不为0了调用dequeue()取出元素
- count值减一,如果得到值还大于1的话说明队列中还有元素,唤醒notEmpty的线程
- 解锁
- 如果出队前容量满了,出队后就还剩一个就唤醒NotFull的线程来添加元素,signalNotFull()方法中需要获取putLock锁才能调用notFull.signal()唤醒线程
总结
这篇文章我们从源码角度讲解了LinkedBlockingQueue的put()方法和take()方法,从源码中我们可以看出来,put()方法和take()各自有一把自己的锁,两个方法的逻辑差不多,一个是放入元素,一个是取出元素,采用了生产者消费者的思想,当队列空的时候,取元素的线程才会阻塞,当队列满的时候,放元素的线程才会阻塞
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)