立正、稍息、入"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

相关文章
立正、稍息、入"ArrayBlockingQueue"(下)
大家好,我是指北君。 在前面的文章中,已经对 ArrayBlockingQueue 进行了一次源码分析,对它的核心源码做了分析,今天来解析一波同为 BlockingQueue 家族中的一员的 LinkedBlockingQueue。它的底层基于单向链表实现。
立正、稍息、入"ArrayBlockingQueue"(下)
立正、稍息、入"ArrayBlockingQueue"(上)
大家好,我是指北君。 在前面的文章中,已经对 ArrayBlockingQueue 进行了一次源码分析,对它的核心源码做了分析,今天来解析一波同为 BlockingQueue 家族中的一员的 LinkedBlockingQueue。它的底层基于单向链表实现。
立正、稍息、入"ArrayBlockingQueue"(上)
|
存储 安全 Java
ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
|
8月前
|
算法
LinkedBlockingQueue
LinkedBlockingQueue
56 0
LinkedBlockingQueue使用
LinkedBlockingQueue使用
237 0
LinkedBlockingQueue使用
|
安全 Java 容器
|
存储 安全
SynchronousQueue详解
SynchronousQueue详解
|
存储 Java 索引
BlockingQueue
网上看了好多文章将线程池的但是似乎都没的多少人会详细讲解里面的任务队列,所以只有自己动手学习其中的任务队列 BlockingQueue
3087 0
BlockingQueue
|
算法
BlockingQueue二
接着上篇BlockingQueue没讲完的 LinkedTransferQueue LinkedTransferQueue是一个由链表结构组成的无界阻塞队列,相对于其它阻塞队列,LinkedBlockingQueue可以算是LinkedBlockingQueue与SynhronoousQueue结合,LinkedtransferQueue是一种无界阻塞队列,底层基于单链表实现,其内部结构分为数据节点、请求节点,基于CAS无锁算法实现
143 0
BlockingQueue二
|
Java
BlockingQueue的使用
一个线程从队列里取数据,一个线程往队列里添加数据 import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExchangerTest {     public static 
1559 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等