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

JUC并发队列及应用

文章目录

    • 1.队列类型
    • 2.无界非阻塞队列ConcurrentLinkedQueue:
    • 3.无界阻塞队列LinkedBlockingQueue:
    • 4.有界阻塞队列ArrayBlockingQueue:
    • 5.带优先级无界阻塞队列PriorityBlockingQueue:
    • 6.无界阻塞延迟队列DelayQueue:
    • 7.额外补充

1.队列类型

阻塞队列:为了保证线程安全采用阻塞线程方式操作队列。
非阻塞队列:不阻塞线程操作队列。
有界队列: 队列长度有限制。
无界队列: 队列长度无限制。

2.无界非阻塞队列ConcurrentLinkedQueue:

实现结构:单向链表
实现线程安全方式:CAS【非阻塞】,poll出队和add/offer方法入队都是采用CAS机制来实现线程安全。
典型应用:Tomcat 中NioEndpoint使用ConcurrentLinkedQueue来接收请求。
特点:性能优越,适用于读多写少的场景。

3.无界阻塞队列LinkedBlockingQueue:

实现方式:单向链表
实现线程安全方式:take 和 put 对应【阻塞方法】,poll和offer对应【非阻塞方法】
如果take执行过程中队列为空/put队列已满则会陷入阻塞。poll/offer不会阻塞,而是直接返回null/false。
采用两个独占锁来实现头尾节点操作原子性,并都配备了一个条件队列,存放被阻塞的线程,结合入队出队可实现生产消费模型。【入队出队可同时运行
典型应用:JDK 线程池
特点:容量可达Integer.MAX_VALUE值,先进先出存取分离,并且能保证节点前后置不乱,删除节点时加两把锁,性能优越

4.有界阻塞队列ArrayBlockingQueue:

实现方式:数组
实现线程安全方式: 全局独占锁
典型应用:异步日志打印等
特点:同时只能有一个线程进行入队或者出队操作。size计算精确。

5.带优先级无界阻塞队列PriorityBlockingQueue:

实现方式:平衡二叉树堆 数组进行存储
实现线程安全方式:一个独占锁
典型应用:任务调度资源分配事件处理
特点:同时只能有一个线程进行入队或出队,但是由于是无界的,可一直put,不会陷入阻塞,内置使用CAS算法进行扩容操作,可自定以优先级比较规则。

6.无界阻塞延迟队列DelayQueue:

实现方式:优先级队列,且元素必须要实现Delayed接口
实现线程安全方式: 独占锁
典型应用:定时发送邮件定期数据清理订单支付延时发送消息缓存过期清除
特点:每个元素都有个过期时间、只有过期元素才会出队列。可实现延时功能。也可自定义元素比较规则。

7.额外补充

1.JDK7新增ThreadLocalRandom类,弥补传统Random类在多线程高并发请求下性能缺陷。
Random采用CAS机制来确保seed种子一定是基于上个seed种子生成的新种子,然后参与计算生成随机数。

   protected int next(int bits) {long oldseed, nextseed;AtomicLong seed = this.seed;do {oldseed = seed.get();nextseed = (oldseed * multiplier + addend) & mask;} while (!seed.compareAndSet(oldseed, nextseed));return (int)(nextseed >>> (48 - bits));}

CAS机制在高并发多线程下的缺陷就是不断自旋获取锁,大量占用CPU
为了解决这个问题,引入了ThreadLocalRandom类。将seed挪到Thread实例对象中。每个Thread都有一分属于自己的seed 也就是ThreadLocalRandomSeed
在这里插入图片描述
带大家看下这个ThreadLocalRandom类生成随机数nextInt()方法执行逻辑

	@Overridepublic int nextInt() {return mix32(nextSeed());}// 因此这个nextSeed() 要保证原子性。final long nextSeed() {Thread t; long r; // read and update per-thread seedU.putLong(t = Thread.currentThread(), SEED,r = U.getLong(t, SEED) + (t.threadId() << 1) + GOLDEN_GAMMA);return r;}// 逻辑计算是固定的。private static int mix32(long z) {z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);}

SEED来源于Thread 类中threadLocalRandomSeed 值。由于该是线程独立私有,因此多线程情况下不会发生生成同样随机数的情况,同时也避免了CAS所带来的锁竞争引发的CPU资源损耗。
在这里插入图片描述
2.SimpleDateFormat线程不安全,多线程情况下建议放入ThreadLocal中,记得使用完手动删除避免内存泄漏
3.Timer类定时任务执行多个TimerTask,如果存在一个方法抛出异常则会自动停止所有task,解决方案就是使用ScheduledThreadPoolExecutor中的schedule方法执行多个task。
4.需要复用且会被下游方法修改的参数要进行深复制,否则会出现错误结果。引用类型作为集合作为另一个集合的构造函数的参数,【引用传递】使用同一份引用,此时要采用深复制
5.线程池和线程构建需要补充业务相关的名称,便于排查异常。
6.线程池关闭记得调用shutdown关闭线程池。
7.线程池使用FutureTask,为了避免在DiscardPolicy/DiscardOldestPolicy策略下调用get方法陷入阻塞,建议使用带超时时间的get方法。


http://www.mrgr.cn/news/69865.html

相关文章:

  • 项目技术栈-解决方案-web3去中心化
  • 【React】条件渲染——逻辑与运算符
  • Linux最深刻理解页表于物理内存
  • Docker--Docker是什么和对Docker的了解
  • 商品规格递归拼接
  • 博弈论(零和博弈)英文版题解
  • 计算机研究生方向,零基础入门到精通,收藏这篇就够了
  • halcon仿射变换核心技术分析
  • 2024年【危险化学品生产单位主要负责人】找解析及危险化学品生产单位主要负责人考试技巧
  • 910. 最小差值 II
  • 《Python网络安全项目实战》项目3 处理文件中的数据_练习题(2)
  • GB/T 43206—2023信息安全技术信息系统密码应用测评要求(二)
  • 闭包的知识
  • CMS那点事
  • 分布式唯一ID生成(二): leaf
  • 网站架构知识之Ansible进阶(day022)
  • JavaScript深拷贝与浅拷贝:区别及实现方法详解
  • 【计算机架构】什么是 ROM
  • GPIO 唤醒深度睡眠的esp32-c3
  • CouchdbH2database未授权
  • arkUI:相对布局(RelativeContaine)
  • 环形链表问题(图 + 证明 + 题)
  • Kruskal和Prim
  • 【前端打包必看】webpack入口与出口配置全解析(8)
  • c++常用的新特性-->day04
  • 布耗!对面是炸鱼的!!快让我的18岁舍友直接帮我拿下对局——如何用HarmonyOS鸿蒙操作系统实现自由流转