LinkedBlockingQueue有界队列

初始化

  创建的时候,实际就是指定了队列大小 capacity,然后队列node其实就是个单向列表结构,item 是当前元素,next 是下一个元素的引用。默认head指针和last指针都是指向这个空节点。ps: 是不是有点责任链模式的感觉呢。

put

put 从队列尾部插入节点

  1. 首先也是获取到了 ReentrantLock 锁 ,进行 putLock 加锁。
  2. 添加元素之前,先 while (count.get() == capacity) 判断一下,count 是队列中的个数,capacity 是指定的最大个数。相等就说明队列满了,那当前线程就要park挂起释放锁。
  3. enqueue(node) 这个是核心,走到这里说明可以添加元素了。 "last = last.next = node;" 这行代码的意思就是先将 last.next 的指针指向node,然后再把 last 也指向它,说明是最后一个元素(初始化的时候我们把 head last 都是指向null这个头节点的嘛,现在头节点还是保持不动)。
  4. c 是此次put前的元素个数,然后count自增1了。c + 1 < capacity 说明队列没有满,也尝试去唤醒阻塞的队列 (这种代码确实可读性不太好,像hashmap里面也是大量这样的代码)。
  5. c == 0 ,表示之前队列位空,说明可能有线程执行take操作被阻塞住了

take

take 从头部弹出节点

  1. 先获取到 ReentrantLock 锁 ,进行 takeLock 加锁。
  2. while (count.get() == 0)那就说明队列中没有元素,然后把自己挂起来一直等待(前面不是说了put也会唤醒等待的元素嘛,那个时候就会唤醒这个线程)。
  3. dequeue();就是弹出第一个节点
  4. c = count.getAndDecrement(); 首先是c = count的,然后 count-1 ,也就是说 c-count=1
  5. c > 1,也就是说task之前起码是有2个线程等待的,现在 dequeue() 之后起码还有一条数据,那就去唤醒线程
  6. c == capacity,就是说 take 之前满了,那就很可能有人put的时候阻塞了,现在就去尝试唤醒它

 

posted @   吴磊的  阅读(507)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
//生成目录索引列表
点击右上角即可分享
微信分享提示