LinkedBlockingQueue原理探究

发布时间:2024年01月09日

类图结构

同样首先看一下LinkedBlockingQueue的类图结构,以便从全局对LinkedBlockingQueue有个直观的了解。

在这里插入图片描述
由类图可以看到,LinkedBlockingQueue也是使用单向链表实现的,其也有两个Node,分别用来存放首、尾节点,并且还有一个初始值为0的原子变量count,用来记录队列元素个数。

另外还有两个ReentrantLock的实例,分别用来控制元素入队和出队的原子性,其中takeLock用来控制同时只有一个线程可以从队列头获取元素,其他线程必须等待,putLock控制同时只能有一个线程可以获取锁,在队列尾部添加元素,其他线程必须等待。

另外,notEmpty和notFull是条件变量,它们内部都有一个条件队列用来存放进队和出队时被阻塞的线程,其实这是生产者—消费者模型。

在这里插入图片描述

  • 当调用线程在LinkedBlockingQueue实例上执行take、poll等操作时需要获取到takeLock锁,从而保证同时只有一个线程可以操作链表头节点。

    另外由于条件变量notEmpty内部的条件队列的维护使用的是takeLock的锁状态管理机制,所以在调用notEmpty的await和signal方法前调用线程必须先获取到takeLock锁,否则会抛出IllegalMonitorStateException异常。

    notEmpty内部则维护着一个条件队列,当线程获取到takeLock锁后调用notEmpty的await方法时,调用线程会被阻塞,然后该线程会被放到notEmpty内部的条件队列进行等待,直到有线程调用了notEmpty的signal方法。

  • 在LinkedBlockingQueue实例上执行put、offer等操作时需要获取到putLock锁,从而保证同时只有一个线程可以操作链表尾节点。

    同样由于条件变量notFull内部的条件队列的维护使用的是putLock的锁状态管理机制,所以在调用notFull的await和signal方法前调用线程必须先获取到putLock锁,否则会抛出IllegalMonitorStateException异常。

    notFull内部则维护着一个条件队列,当线程获取到putLock锁后调用notFull的await方法时,调用线程会被阻塞,然后该线程会被放到notFull内部的条件队列进行等待,直到有线程调用了notFull的signal方法。

在这里插入图片描述
默认队列容量为0x7fmf,用户也可以自己指定容量,所以从一定程度上可以说LinkedBlockingQueue是有界阻塞队列。

LinkedBlockingQueue原理介绍

offer操作

向队列尾部插入一个元素,如果队列中有空闲则插入成功后返回true,如果队列已满则丢弃当前元素然后返回false。

如果e元素为null则抛出NullPointerException异常。另外,该方法是非阻塞的。

在这里插入图片描述
在这里插入图片描述

put操作

向队列尾部插入一个元素,如果队列中有空闲则插入后直接返回,如果队列已满则阻塞当前线程,直到队列有空闲插入成功后返回。

如果在阻塞时被其他线程设置了中断标志,则被阻塞线程会抛出InterruptedException异常而返回。

另外,如果e元素为null则抛出NullPointerException异常。

在这里插入图片描述

poll操作

从队列头部获取并移除一个元素,如果队列为空则返回null,该方法是不阻塞的。
在这里插入图片描述
在这里插入图片描述

peek操作

获取队列头部元素但是不从队列里面移除它,如果队列为空则返回null。该方法是不阻塞的。
在这里插入图片描述

take操作

获取当前队列头部元素并从队列里面移除它。

如果队列为空则阻塞当前线程直到队列不为空然后返回元素,如果在阻塞时被其他线程设置了中断标志,则被阻塞线程会抛出InterruptedException异常而返回。

在这里插入图片描述

remove操作

删除队列里面指定的元素,有则删除并返回true,没有则返回false。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

size操作

获取当前队列元素个数。

在这里插入图片描述
在这里插入图片描述

文章来源:https://blog.csdn.net/zhuyufan1986/article/details/135483065
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。