当前位置: 首页 > news >正文

icp备案网站信息填写珠海网站制作网络推广

icp备案网站信息填写,珠海网站制作网络推广,如何制作h5海报,新式装修目录 AQS底层源码深度剖析-BlockingQueue BlockingQueue定义 队列类型 队列数据结构 ArrayBlockingQueue LinkedBlockingQueue DelayQueue BlockingQueue API 添加元素 检索(取出)元素 BlockingQueue应用队列总览图 AQS底层源码深度剖析-BlockingQueue【重点中的重…

目录

AQS底层源码深度剖析-BlockingQueue

BlockingQueue定义

队列类型

队列数据结构

ArrayBlockingQueue

LinkedBlockingQueue

DelayQueue

BlockingQueue API

添加元素

检索(取出)元素

BlockingQueue应用队列总览图

AQS底层源码深度剖析-BlockingQueue【重点中的重点】

看源码前,先要明白Condition的含义:

BlockingQueue源码会涉及三个队列【重点掌握】:

put()源码剖析:

 take()源码剖析:

 总结:


AQS底层源码深度剖析-BlockingQueue

BlockingQueue定义

线程通信一个工具,在任意时刻,不管并发有多高,在单台JVM上,同一时间永远只能有一个线程能够对队列进行入队或者出队操作。

官方点说:BlockingQueue,是java.util.concurrent包提供的用于解决并发生产者-消费者问题的最有用的类,它的特性是在任意时刻只有一个线程可以进行take或put操作,并且BlockingQueue提供了超时return null的机制,在许多生产应用场景里都可以看到这个工具的身影。

应用场景:

线程池,springcloud-Eureka的三级缓存,Nacos,Netty,MQ

队列类型

  1. 无限队列 (unbounded queue ) - 几乎可以无限增长
  2. 有限队列 ( bounded queue ) - 定义了最大容量

队列数据结构

队列实质就是一种存储数据的结构

  • 通常用链表或者数组实现
  • 一般而言队列具备FIFO先进先出的特性,当然也有双端队列(Deque)优先级队列
  • 主要操作:入队(EnQueue)与出队(Dequeue)

常见的4种阻塞队列

  • ArrayBlockingQueue 由数组支持的有界队列
  • LinkedBlockingQueue 由链接节点支持的可选有界队列
  • PriorityBlockingQueue 由优先级堆支持的无界优先级队列
  • DelayQueue 由优先级堆支持的、基于时间的调度队列

ArrayBlockingQueue

队列基于数组实现,容量大小在创建ArrayBlockingQueue对象时已定义好

数据结构如下图:

 队列创建:

BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>();

应用场景

在线程池中有比较多的应用,生产者消费者场景

工作原理

基于ReentrantLock保证线程安全,根据Condition实现队列满时的阻塞

LinkedBlockingQueue

是一个基于链表的无界队列(理论上有界)

BlockingQueue<String> blockingQueue = new LinkedBlockingQueue<>();

上面这段代码中,blockingQueue的容量将设置为Integer.MAX_VALUE

向无限容量的队列中添加元素的所有操作都将永远不会阻塞,因此它可以增长到非常大的容量(注意 这里不是说不会加锁保证线程安全,同样会加锁来保证同一时刻只会有一个线程对队列添加元素或取出元素成功)

使用无限容量的BlockingQueue设计生产者-消费者模型时最重要的是消费者应该能够像生产者向队列添加消息一样快的消费消息。否则存储消息数据的内存可能会填满,然后得到一个OutOfMemory异常

DelayQueue

由优先级堆支持的、基于时间的调度队列,内部基于无界队列PriorityQueue实现,而无界队列基于数组的扩容实现。

队列创建:

BlockingQueue<String> blockingQueue = new DelayQueue();

要求:

入队的对象必须要实现Delayed接口,而Delayed集成自Comparable接口

应用场景:

电影票

工作原理:

队列内部会根据时间优先级进行排序。延迟类线程池周期执行。

BlockingQueue API

BlockingQueue 接口的所有方法可以分为两大类:负责向队列添加元素的方法和检索(取出)这些元素的方法。在队列满/空的情况下,来自这两个组的每个方法的行为都不同。

添加元素

方法

说明

add()

如果插入成功则返回 true,否则抛出 IllegalStateException 异常

put()

将指定的元素插入队列,如果队列满了,那么会阻塞直到有空间插入

offer()

如果插入成功则返回 true,否则返回 false

offer(E e, long timeout, TimeUnit unit)

尝试将元素插入队列,如果队列已满,那么会阻塞直到有空间插入

检索(取出)元素

方法

说明

take()

获取队列的头部元素并将其删除,如果队列为空,则阻塞并等待元素变为可用

poll(long timeout, TimeUnit unit)

检索并删除队列的头部,如有必要,等待指定的等待时间以使元素可用,如果超时,则返回 null

在构建生产者 - 消费者程序时,这些方法是 BlockingQueue 接口中最重要的构建块。

BlockingQueue应用队列总览图

应用队列:存储消息数据的队列。无论是consumer还是producer,想要对应用队列中的消息数据进行操作(存入或取出)时,必须先获取到锁对象。如果获取不到锁,则无法操作。

(1) 

极端情况下:

当producer把队列容量放满了,那么producer释放锁,producer阻塞,让consumer获取到锁 然后去消费消息数据

同理当consumer消费完队列中的消息数据,那么consumer会释放锁,consumer阻塞,让producer获取到锁,然后去生产并且加入消息数据到队列中

普通情况下:

当然应用队列中没有放满,consumer也可以消费取出数据 。队列数据没有被消费完时,producer也可以生产消息并且存入应用队列中。

(2) 当producer在同步队列中存入一个消息数据后,会进行通知consumer,consumer接收到通知,会从条件队列中转移到阻塞CLH队列,在CLH阻塞队列中的consumer会进行消费应用队列中存储的消息数据

 AQS底层源码深度剖析-BlockingQueue【重点中的重点】

以下会深度剖析BlockingQueue的put()和take()方法的底层实现源码,一步步走完后会进行总结。如果不看源码,就没有任何的说服性。

看源码前,先要明白Condition的含义:

Condition的实现ConditionObject:

ConditionObject是AQS类的内部类,在BlockingQueue底层的实现中主要功能有:等待队列,等待和通知。

等待队列,等待和通知:源码中会使用到notEmpty和notFull

notEmpty: 消费者对应的等待队列。有啥用?当应用队列中的数据被消费完毕后,最后一次消费数据的消费者会释放掉自己持有的锁,然后调用notEmpty.await()加入到notEmpty等待队列的尾部。并且会调用notFull.signal()表示唤醒生产者等待队列中的一个节点加入到CLH阻塞队列中去[因为队列中没有数据啦,所以要唤醒生产者加入到CLH阻塞队列中]。

notFull:生产者对应的等待队列。有啥用?当应用队列中的空间已经被数据占满后,最后一次生产数据的生产者会释放掉自己持有的锁,然后调用notFull.await()加入到notFull等待队列的尾部。并且会调用notEmpty.signal()表示唤醒消费者等待队列中的一个节点加入到CLH阻塞队列中去[因为队列的空间被数据占满啦,所以要唤醒消费者加入到CLH阻塞队列中]。

补充:

其实唤醒也不是说只有当极端情况下(队列被占满或队列为空)才会进行唤醒消费者或生产者,其实每一次往队列中进行加入或取出数据都会导致各自的唤醒操作。

eg:加入一条数据会导致唤醒一个消费者等待队列中的消费者加入到CLH队列。取出一条数据时同理即可。

BlockingQueue源码会涉及三个队列【重点掌握】:

1.应用队列:

存放消息数据,模拟出的一个虚拟队列概念,可以认为是一个虚拟的不存在的存储结构,底层是使用数组进行存储插入应用队列的数据,以此模拟出一个应用队列。

2.CLH双端阻塞队列:存储封装当前线程对象对应的Node节点,是底层真实存在的一个队列

3.条件等待队列:这个就是上面Condition中记录的:notEmpty和notFull

put()源码剖析:

API层面调用put()方法其实就是生产者加入一条数据到应用队列

1.

 2.

3.put方法解析

生产者插入一个数据到应用队列,以下为具体的分析过程:

对put()方法中的await()方法解析一下:

对put方法中的equeue()方法解析:

 take()源码剖析:

 API层面调用take()方法其实就是生产者从应用队列中取出一条数据

1.

2.

3.

 对take()中的await方法解析: 

 对take()中的dequeue方法解析:

 总结:

(1)记清楚三个队列

(2)明白Condition的含义

(3)画出图即可

其实也没啥,看懂了也挺简单的,关于这个源码的图,使用processon绘制:

 ProcessOn Flowchart

http://www.yayakq.cn/news/621689/

相关文章:

  • 公司怎么建立自己的网站wordpress微信群二维码
  • 德州网站建设维护影视网站建设需要学什么
  • 济源市建设管理处网站网站导航的重要性
  • 做药物分析网站深圳市专业的做网站
  • 界面设计是什么专业重庆seo扣费
  • 有那种做订单的网站吗wordpress指定标签不同样式
  • 积分商城网站开发网上商城系统论文
  • wordpress站群被谷歌k织梦网站密码
  • 网站验证码目录wordpress找不到根目录
  • 网站图片像素多少建设兵团12师教育局网站
  • 福建省网站建设深圳网络推广网络
  • 怀化网站建设哪家便宜重庆网站seo推广公司
  • c 教学网站开发金华网站建设大型网页建设
  • 最低价网站建设墨刀制作网页教程
  • 贵州碧江区住房和城乡建设局网站衡阳建设网站制作
  • 做网站费用入什么科目wordpress 展开目录
  • 响应式网站设计规则wordpress前台评论显示英文
  • 建设局网站公告北京网站设计公司哪家公司好
  • 建设网站的报价小学生做创客大赛网站的题
  • 仿别人的网站违法嘛拓客软件
  • 大良网站设计价格钓鱼网站怎么做
  • 学做网站用什么服务器2345网址大全手机版
  • 什么管理系统好做广东工厂搜索seo
  • 引流网站建设教程深圳人才市场
  • 东圃做网站公司电脑上制作ppt的步骤
  • 电子商务网站建设答案重庆建设医院官方网站
  • 做网站准备的资料网站建设工作任务
  • 网站追踪如何做建立个公司网站
  • 网站做多少外链网站留言短信通知
  • 精美ppt模板免费下载网站建网站花钱吗