写点什么

LinkedBlockingQueue 源码分析 - 新增和删除

作者:zarmnosaj
  • 2022 年 7 月 07 日
  • 本文字数:1478 字

    阅读完需:约 5 分钟

LinkedBlockingQueue 源码分析-新增和删除

新增

put 方法,把 e 新增到队列的尾部,如果有可以新增的空间的话,直接新增成功,否则当前线程陷入等待,源码:


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();}private void enqueue(Node<E> node) { last = last.next = node;}
复制代码


if (e == null) throw new NullPointerException(); 如果 e 为空,则抛出异常


int c = -1; 预先设置 c 为 -1,如果负数为则会新增失败


while (count.get() == capacity) { }队列满了则线程阻塞,等待其他线程的唤醒(其他线程 take 成功后就会唤醒此处被阻塞的线程,await 无限等待


enqueue(node); 队列没有满,直接新增到队列的尾部


c = count.getAndIncrement(); 新增计数赋值


if (c + 1 < capacity) 如果链表现在的大小 小于链表的容量,说明队列未满,尝试唤醒一个 put 的等待线程


if (c == 0) signalNotEmpty();c==0,代表队列里面有一个元素,尝试唤醒一个 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;}private E dequeue() {    Node<E> h = head;    Node<E> first = h.next;    h.next = h; // help GC    head = first;    E x = first.item;    first.item = null;    return x;}
public E peek() { if (count.get() == 0) return null; final ReentrantLock takeLock = this.takeLock; takeLock.lock(); try { Node<E> first = head.next; if (first == null) return null; else return first.item; } finally { takeLock.unlock(); }}
private E dequeue() { Node<E> h = head; Node<E> first = h.next; h.next = h; // help GC head = first; E x = first.item; first.item = null; return x;}
复制代码


int c = -1; 默认负数,代表失败


final AtomicInteger count = this.count; count 代表当前链表数据的真实大小


while (count.get() == 0) { notEmpty.await(); } 空队列时,阻塞,等待其他线程唤醒


x = dequeue(); 非空队列,从队列的头部拿一个出来


if (c > 1) notEmpty.signal();如果队列里面有值,从 take 的等待线程里面唤醒


if (c == capacity) signalNotFull(); 如果队列空闲还剩下一个,尝试从 put 的等待线程中唤醒

发布于: 刚刚阅读数: 3
用户头像

zarmnosaj

关注

靡不有初,鲜克有终 2020.02.06 加入

成都后端混子

评论

发布
暂无评论
LinkedBlockingQueue源码分析-新增和删除_7月月更_zarmnosaj_InfoQ写作社区