立正、稍息、入"ArrayBlockingQueue"(中)

简介: 大家好,我是指北君。在前面的文章中,已经对 ArrayBlockingQueue 进行了一次源码分析,对它的核心源码做了分析,今天来解析一波同为 BlockingQueue 家族中的一员的 LinkedBlockingQueue。它的底层基于单向链表实现。

offer() 方法做了以下几件事情:

  1. 检查需要入队的元素是否为 null。
  2. 判断队列是否满了,满了就返回 false。
  3. 队列没有满,创建一个新的 Node 节点。
  4. putLock 锁加锁,不让其他线程操作队列。
  5. 当队列没有满队的时候,将元素入队并且将局部变量 c 设置为入队之前元素的数量,元素数量 + 1。
  6. 再次判断队列是否满了,如果队列中还有空位,则唤醒正在阻塞的入队线程。这些阻塞的线程来自 put()、offer(E e, long timeout, TimeUnit unit) 方法。
  7. 释放 putLock 锁
  8. 当入队之前是一个空队列的时候,调用 signalNotEmpty() 方法开启 takeLock 出队锁,将阻塞在 notEmpty 条件队列中的线程唤醒。

enqueue() 方法的源码比较简单,就是将 last 节点的 next 指向需要入队的元素,如下图所示。39.jpg


add()

40.png

add() 方法调用的是 offer() 方法,它在队列满了的时候不是返回 false 而是抛出一个 Queue full 异常。


put()


41.png

put() 方法和 offer()、and() 的方法大致相同,不同的是对队列满了之后的操作,offer() 是直接返回 false,and() 是抛出异常,put() 则是将线程加入到 notFull 条件队列中阻塞入队线程。


offer(E e, long timeout, TimeUnit unit)


这是一个带超时时间的 offer() 方法。


42.png


43.png

这个方法是在一定时间内元素等待入队,就是在 timeout 时间内队列中有空余位置就将元素加入单向链表的队尾,如果在 timeout 时间内元素还没有入队,就返回 false。

入队总结

LinkedBlockingQueue 的入队一共有 offer()、add()、put()、offer(E e, long timeout, TimeUnit unit) 四种方法。这四种方法在队列满了之后的处理是不同的:

  1. offer() 方法在队列满了之后就返回 false。
  2. add() 方法在内部调用的是 offer() 方法,当队列满了就抛出 Queue full 异常。
  3. put() 方法在队列满了之后会将线程加入 notFull 中,等待被唤醒后加入队列。
  4. offer(E e, long timeout, TimeUnit unit) 方法在队列满了之后会等待一段 timeout 的时间,在这时间内入队就返回 true,在这段时间内未能入队就返回 false。
  5. 每个方法在入队完后都会唤醒在 notEmpty 队列中等待出队的线程。


出队


LinkedBlockingQueue 的出队也有几种不同的方法,它们对于空队列的处理方式各不相同。


poll()


44.png45.png

poll() 方法在出队的时候做了以下几件事情:

  1. 先取出队列中元素的数量
  2. 队列的非空检查,当队列是空的,则返回 false。
  3. 初始化一个局部的元素变量。
  4. takeLock 出队锁加锁,不让其他线程操作队列的出队。
  5. 当队列中有元素的时候,将队列中的第一个元素弹出。
  6. 判断队列中是否还有元素,唤醒阻塞在 notEmpty 条件队列上的线程。
  7. takeLock 出队锁解锁
  8. 在原队列是满队的情况下,唤醒阻塞在 notFull 条件队列上的线程。

dequeue() 方法会将 LinkedBlockingQueue 中第一个元素取出。取的并不是 head 中的item,而是 head.next 中的 item。


46.jpg

相关文章
|
存储 安全 Java
ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
|
5月前
|
算法
LinkedBlockingQueue
LinkedBlockingQueue
46 0
阻塞队列BlockingQueue
阻塞队列BlockingQueue
59 0
阻塞队列BlockingQueue
|
存储 缓存 安全
JUC之阻塞队列解读(BlockingQueue)
JUC之阻塞队列解读(BlockingQueue)
|
算法
BlockingQueue二
接着上篇BlockingQueue没讲完的 LinkedTransferQueue LinkedTransferQueue是一个由链表结构组成的无界阻塞队列,相对于其它阻塞队列,LinkedBlockingQueue可以算是LinkedBlockingQueue与SynhronoousQueue结合,LinkedtransferQueue是一种无界阻塞队列,底层基于单链表实现,其内部结构分为数据节点、请求节点,基于CAS无锁算法实现
134 0
BlockingQueue二
|
缓存 安全 Java
JUC系列学习(四):线程池阻塞队列BlockingQueue及其相关实现ArrayBlockingQueue、LinkedBlockingQueue
线程池阻塞队列BlockingQueue及其相关实现ArrayBlockingQueue、LinkedBlockingQueue
121 0
|
存储 Java 索引
BlockingQueue
网上看了好多文章将线程池的但是似乎都没的多少人会详细讲解里面的任务队列,所以只有自己动手学习其中的任务队列 BlockingQueue
3072 0
BlockingQueue
|
缓存 安全 Java
JUC - BlockingQueue
JUC - BlockingQueue
136 0
JUC - BlockingQueue
|
消息中间件 存储 Java
阻塞队列 BlockingQueue
学数据结构时学过队列,特点是FIFO,先进先出。那么什么阻塞队列呢?一起来看看。
阻塞队列 BlockingQueue
|
存储 缓存 安全
BlockingQueue 阻塞队列详解(上)
BlockingQueue 是一个 Queue , 它是一个线程安全的阻塞队列接口。 ​
320 0
BlockingQueue 阻塞队列详解(上)

热门文章

最新文章