多线程篇(阻塞队列- LinkedBlockingDeque)(持续更新迭代)

本文主要是介绍多线程篇(阻塞队列- LinkedBlockingDeque)(持续更新迭代),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、LinkedBlockingDeque是什么

二、核心属性详解

三、核心方法详解

addFirst(E e)

offerFirst(E e)

putFirst(E e)

removeFirst()

pollFirst()

takeFirst()

其他

四、总结


一、LinkedBlockingDeque是什么

首先queue是一种数据结构,一个集合中,先进后出,有两种实现的方式,数组和链表。

从尾部追加,从头部获取。

Deque是两端都可以添加,且两端都可以获取,所以它的方法会有一系列的Last,Frist语义,添加或获取等操作

会指明哪个方向的,这也是Deque接口的定义。

那如果你不指定语义 如add()方法,他会默认调用addLast

综上所述,LinkedBlockingDeque是一个线程安全的双端阻塞队列。

二、核心属性详解

相对于LinkedBlockingQueue 他只能使用一把锁,不能分成put 和 take两把锁。

因为此时双端都可以put 和 take,所以只能使用一个锁,通过锁,对其链表实现线程安全的操作。

    //队列的头尾节点transient Node<E> first;transient Node<E> last;//队列中元素的数量private transient int count;//指定的队列的容量,默认Int最大值private final int capacity;//实现线程安全的使用的锁final ReentrantLock lock = new ReentrantLock();//获取元素的时候如果空了会使用它让其自己等待private final Condition notEmpty = lock.newCondition();//添加元素的时候如果满了(count == capacity)会使用它让其自己等待private final Condition notFull = lock.newCondition();

三、核心方法详解

下面会列举First系列的方法,因为last系列相对于first只是链表方向不一样,操作都是一致的。

addFirst(E e)

调用offerFirst 如果未成功 则抛出异常

    public void addFirst(E e) {if (!offerFirst(e))throw new IllegalStateException("Deque full");}

offerFirst(E e)

在链表的头部添加一个元素,使用ReentrantLock 保证线程安全

    public boolean offerFirst(E e) {if (e == null) throw new NullPointerException();Node<E> node = new Node<E>(e);//获取锁final ReentrantLock lock = this.lock;lock.lock();try {//把当前元素对应的节点放到头结点那里return linkFirst(node);} finally {lock.unlock();}}private boolean linkFirst(Node<E> node) {//如果元素已经超出容量,返回添加失败if (count >= capacity)return false;//链表的操作,用的是双向链表,first变成自己,之前的first是自己的nextNode<E> f = first;node.next = f;first = node;if (last == null)last = node;elsef.prev = node;//元素统计数量加1++count;//唤醒那些因为获取不到元素而阻塞的线程notEmpty.signal();return true;}

putFirst(E e)

相对于offer一个元素 如果元素数量已到达容量上线,会阻塞住等待元素被取走才放入

在juc下面 put add take等语义都是一致的

    public void putFirst(E e) throws InterruptedException {if (e == null) throw new NullPointerException();Node<E> node = new Node<E>(e);//获取锁final ReentrantLock lock = this.lock;lock.lock();try {//添加失败就阻塞住等待唤醒while (!linkFirst(node))notFull.await();} finally {lock.unlock();}}

removeFirst()

从头结点移除一个元素,调用的是pollFirst,拿出元素返回,元素==null会抛出异常

    public E removeFirst() {E x = pollFirst();if (x == null) throw new NoSuchElementException();return x;}

pollFirst()

取出first元素并返回,会返回null


    public E pollFirst() {//加锁final ReentrantLock lock = this.lock;lock.lock();try {// 取出first, 链表的操作和count的维护以及唤醒添加元素因为容量到达上线的等待的线程return unlinkFirst();} finally {lock.unlock();}}

takeFirst()

获取一个first元素,区别poll 在于会阻塞等待

    public E takeFirst() throws InterruptedException {final ReentrantLock lock = this.lock;//获取锁lock.lock();try {E x;//拿不到就阻塞等待,等待添加元素的时候被其他线程唤醒while ( (x = unlinkFirst()) == null)notEmpty.await();return x;} finally {lock.unlock();}}

其他

对于last系列方法,只是链表的操作方向不一样而已

其次默认的不带last 和 first系列的方法,即原始的add put等方法,可以等同LinkedBlockingQueue。

LinkedBlockingDeque内部是一个双向链表,支持了链表两端操作,所以方法不一一介绍,原理都是一样。

四、总结

LinkedBlockingDeque使用双端队列,通过ReentrantLock保证线程安全,实现了双端的线程安全的阻塞队列。

这篇关于多线程篇(阻塞队列- LinkedBlockingDeque)(持续更新迭代)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1148146

相关文章

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

AI行业应用(不定期更新)

ChatPDF 可以让你上传一个 PDF 文件,然后针对这个 PDF 进行小结和提问。你可以把各种各样你要研究的分析报告交给它,快速获取到想要知道的信息。https://www.chatpdf.com/

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2431 poj 3253 优先队列的运用

poj 2431: 题意: 一条路起点为0, 终点为l。 卡车初始时在0点,并且有p升油,假设油箱无限大。 给n个加油站,每个加油站距离终点 l 距离为 x[i],可以加的油量为fuel[i]。 问最少加几次油可以到达终点,若不能到达,输出-1。 解析: 《挑战程序设计竞赛》: “在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一

GIS图形库更新2024.8.4-9.9

更多精彩内容请访问 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信:digital_twin123 Cesium 本期发布了1.121 版本。重大新闻,Cesium被Bentley收购。 ✨ 功能和改进 默认启用 MSAA,采样 4 次。若要关闭 MSAA,则可以设置scene.msaaSamples = 1。但是通过比较,发现并没有多大改善。

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.