多线程篇(阻塞队列- 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

相关文章

MySQL新增字段后Java实体未更新的潜在问题与解决方案

《MySQL新增字段后Java实体未更新的潜在问题与解决方案》在Java+MySQL的开发中,我们通常使用ORM框架来映射数据库表与Java对象,但有时候,数据库表结构变更(如新增字段)后,开发人员可... 目录引言1. 问题背景:数据库与 Java 实体不同步1.1 常见场景1.2 示例代码2. 不同操作

Java使用多线程处理未知任务数的方案介绍

《Java使用多线程处理未知任务数的方案介绍》这篇文章主要为大家详细介绍了Java如何使用多线程实现处理未知任务数,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 知道任务个数,你可以定义好线程数规则,生成线程数去跑代码说明:1.虚拟线程池:使用 Executors.newVir

一文详解SQL Server如何跟踪自动统计信息更新

《一文详解SQLServer如何跟踪自动统计信息更新》SQLServer数据库中,我们都清楚统计信息对于优化器来说非常重要,所以本文就来和大家简单聊一聊SQLServer如何跟踪自动统计信息更新吧... SQL Server数据库中,我们都清楚统计信息对于优化器来说非常重要。一般情况下,我们会开启"自动更新

Mybatis从3.4.0版本到3.5.7版本的迭代方法实现

《Mybatis从3.4.0版本到3.5.7版本的迭代方法实现》本文主要介绍了Mybatis从3.4.0版本到3.5.7版本的迭代方法实现,包括主要的功能增强、不兼容的更改和修复的错误,具有一定的参考... 目录一、3.4.01、主要的功能增强2、selectCursor example3、不兼容的更改二、

JAVA封装多线程实现的方式及原理

《JAVA封装多线程实现的方式及原理》:本文主要介绍Java中封装多线程的原理和常见方式,通过封装可以简化多线程的使用,提高安全性,并增强代码的可维护性和可扩展性,需要的朋友可以参考下... 目录前言一、封装的目标二、常见的封装方式及原理总结前言在 Java 中,封装多线程的原理主要围绕着将多线程相关的操

Go使用pprof进行CPU,内存和阻塞情况分析

《Go使用pprof进行CPU,内存和阻塞情况分析》Go语言提供了强大的pprof工具,用于分析CPU、内存、Goroutine阻塞等性能问题,帮助开发者优化程序,提高运行效率,下面我们就来深入了解下... 目录1. pprof 介绍2. 快速上手:启用 pprof3. CPU Profiling:分析 C

Spring Boot整合消息队列RabbitMQ的实现示例

《SpringBoot整合消息队列RabbitMQ的实现示例》本文主要介绍了SpringBoot整合消息队列RabbitMQ的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录RabbitMQ 简介与安装1. RabbitMQ 简介2. RabbitMQ 安装Spring

Docker部署Jenkins持续集成(CI)工具的实现

《Docker部署Jenkins持续集成(CI)工具的实现》Jenkins是一个流行的开源自动化工具,广泛应用于持续集成(CI)和持续交付(CD)的环境中,本文介绍了使用Docker部署Jenkins... 目录前言一、准备工作二、设置变量和目录结构三、配置 docker 权限和网络四、启动 Jenkins

Python中多线程和多进程的基本用法详解

《Python中多线程和多进程的基本用法详解》这篇文章介绍了Python中多线程和多进程的相关知识,包括并发编程的优势,多线程和多进程的概念、适用场景、示例代码,线程池和进程池的使用,以及如何选择合适... 目录引言一、并发编程的主要优势二、python的多线程(Threading)1. 什么是多线程?2.

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque