LongAdder和AtomicLong的对比实验

2024-04-13 20:44

本文主要是介绍LongAdder和AtomicLong的对比实验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

LongAdder 的核心思想是热点分离,与 ConcurrentHashMap 的设计思想类似:将value值分离成一个数组,当多线程访问时,通过Hash算法将线程映射到数组的一个元素进行操作;而获取最终的value结果时,则将数组的元素求和。最终,通过 LongAdder 将内部操作对象从单个value值“演变”成一系列的数组元素,从而减小了内部竞争的粒度。

package cn.jaa.cas;import cn.jaa.util.Print;
import cn.jaa.util.ThreadUtil;
import org.junit.Test;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;/*** @Author: Jaa* @Description: LongAdder 和 AtomicLong 的对比测试* @Date 2024/4/13*/
public class LongAdderVSAtomicLongTest {// 每条线程的执行轮数final int TURNS = 1000000000;/*** 使用 AtomicLong 完成 10个线程 每个线程累加1000次*/@Testpublic void testAtomicLong() {// 并发任务数final int TASK_AMOUNT = 10;// 线程池,获取CPU密集型任务线程池ThreadPoolExecutor pool = ThreadUtil.getCpuIntenseTargetThreadPool();// 定义一个原子对象AtomicLong atomicLong = new AtomicLong(0);// 线程同步倒数闩CountDownLatch latch = new CountDownLatch(TASK_AMOUNT);long startTime = System.currentTimeMillis();for (int i = 0; i < TASK_AMOUNT; i++) {// 提交任务pool.submit(() -> {try {for (int j = 0; j < TURNS; j++) {// 执行累加操作atomicLong.incrementAndGet();}} catch (Exception e) {e.printStackTrace();}// 线程执行完毕,倒数闩减一latch.countDown();});}try {// 等待所有线程执行完毕,倒数闩完成所有的倒数操作latch.await();} catch (InterruptedException e) {e.printStackTrace();}float time = (System.currentTimeMillis() - startTime) / 1000F;// 输出统计结果Print.tcfo("运行的时长为:" + time);Print.tcfo("累加结果为:" + atomicLong.get());// [main|LongAdderVSAtomicLongTest.testAtomicLong]:运行的时长为:17.283// [main|LongAdderVSAtomicLongTest.testAtomicLong]:累加结果为:1000000000}/*** 使用 LongAdder 完成 10个线程累加1000万次*/@Testpublic void testLongAdder() {// 并发任务数final int TASK_AMOUNT = 10;// 线程池,获取CPU密集型任务线程池ThreadPoolExecutor pool = ThreadUtil.getCpuIntenseTargetThreadPool();// 定义一个 LongAdder 对象LongAdder longAdder = new LongAdder();// 线程同步倒数闩CountDownLatch latch = new CountDownLatch(TASK_AMOUNT);long startTime = System.currentTimeMillis();for (int i = 0; i < TASK_AMOUNT; i++) {// 提交任务pool.submit(() -> {try {for (int j = 0; j < TURNS; j++) {// 执行累加操作longAdder.add(1);}} catch (Exception e) {e.printStackTrace();}// 线程执行完毕,倒数闩减一latch.countDown();});}// 等待所有线程执行完毕,倒数闩完成所有的倒数操作try {latch.await();} catch (InterruptedException e) {e.printStackTrace();}float time = (System.currentTimeMillis() - startTime) / 1000F;// 输出统计结果Print.tcfo("运行的时长为:" + time);Print.tcfo("累加结果为:" + longAdder.longValue());// [main|LongAdderVSAtomicLongTest.testLongAdder]:运行的时长为:1.191// [main|LongAdderVSAtomicLongTest.testLongAdder]:累加结果为:1000000000}
}

为了进行速度的对比,可以多次运行以上用例多次,每一次运行可以修改 TASK_AMOUNT(次数常量)的值。测试5次,TASK_AMOUNT的值从1000到1?000?000?000,对比出来的速度倍数值如下图(参考,测试时间与计算机配置有关系)

通过对比实验可以看到:当有10个线程总计累加10?000次的时候,AtomicLong的性能更好。随着累加次数的增加,CAS操作的次数急剧增多,AtomicLong的性能急剧下降。从对比实验的结果可以看出,在CAS争用最为激烈的场景下,LongAdder的性能是AtomicLong的8倍。

这篇关于LongAdder和AtomicLong的对比实验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

免费也能高质量!2024年免费录屏软件深度对比评测

我公司因为客户覆盖面广的原因经常会开远程会议,有时候说的内容比较广需要引用多份的数据,我记录起来有一定难度,所以一般都用录屏工具来记录会议内容。这次我们来一起探索有什么免费录屏工具可以提高我们的工作效率吧。 1.福晰录屏大师 链接直达:https://www.foxitsoftware.cn/REC/  录屏软件录屏功能就是本职,这款录屏工具在录屏模式上提供了多种选项,可以选择屏幕录制、窗口

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

HNU-2023电路与电子学-实验3

写在前面: 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能,设计 8 重 2-1 多路复用器。 4.分析模型机的工作原理,设计模型机控制信号产生逻辑。 二、实验内容 1.用 VERILOG 语言设计模型机的 8 重 3-1 多路复用器; 2.用 VERILOG 语言设计模型机的 8 重 2-1 多

类的load方法和initialize方法对比

1. load方法在main()之前被调用,而initialize方法在main()之后调用 load方法实际是在load_images过程中被调用的。load_images会将当前应用依赖的所有镜像(动态库)加载到内存,在在加载中首先是对镜像进行扫描,将所有包含 load 方法的类加入列表 loadable_classes ,然后从这个列表中逐一调用其所包含的 load 方法。 +[XXCl

JavaScript正则表达式六大利器:`test`、`exec`、`match`、`matchAll`、`search`与`replace`详解及对比

在JavaScript中,正则表达式(Regular Expression)是一种用于文本搜索、替换、匹配和验证的强大工具。本文将深入解析与正则表达式相关的几个主要执行方法:test、exec、match、matchAll、search和replace,并对它们进行对比,帮助开发者更好地理解这些方法的使用场景和差异。 正则表达式基础 在深入解析方法之前,先简要回顾一下正则表达式的基础知识。正则

【HarmonyOS】-TaskPool和Worker的对比实践

ArkTS提供了TaskPool与Worker两种多线程并发方案,下面我们将从其工作原理、使用效果对比两种方案的差异,进而选择适用于ArkTS图片编辑场景的并发方案。 TaskPool与Worker工作原理 TaskPool与Worker两种多线程并发能力均是基于 Actor并发模型实现的。Worker主、子线程通过收发消息进行通信;TaskPool基于Worker做了更多场景化的功能封装,例

一些数学经验总结——关于将原一元二次函数增加一些限制条件后最优结果的对比(主要针对公平关切相关的建模)

1.没有分段的情况 原函数为一元二次凹函数(开口向下),如下: 因为要使得其存在正解,必须满足,那么。 上述函数的最优结果为:,。 对应的mathematica代码如下: Clear["Global`*"]f0[x_, a_, b_, c_, d_] := (a*x - b)*(d - c*x);(*(b c+a d)/(2 a c)*)Maximize[{f0[x, a, b,

claude和chatgpt对比:哪一个更适合你?

前言 我们都知道,Claude和ChatGPT都是当前人工智能领域中备受关注的对话生成模型,作为国外AI模型两大巨头,好像他们的实力都不相上下呀! 这时就会有很多同学疑惑,那我如果想选择AI,到底是选择Claude,还是ChatGPT呢?哪个更好呢?他们之间有什么不同独特的地方呢?他们又分别适合在哪些场景使用呢? 技术背景 Claude是由Anthropic公司开发的高性能模型,而Chat

算法复杂度 —— 数据结构前言、算法效率、时间复杂度、空间复杂度、常见复杂度对比、复杂度算法题(旋转数组)

目录 一、数据结构前言 1、数据结构 2、算法 3、学习方法 二、 算法效率 引入概念:算法复杂度  三、时间复杂度 1、大O的渐进表示法 2、时间复杂度计算示例  四、空间复杂度 计算示例:空间复杂度 五、常见复杂度对比 六、复杂度算法题(旋转数组) 1、思路1 2、思路2 3、思路3 一、数据结构前言 1、数据结构         数据结构(D

61.以太网数据回环实验(4)以太网数据收发器发送模块

(1)状态转移图: (2)IP数据包格式: (3)UDP数据包格式: (4)以太网发送模块代码: module udp_tx(input wire gmii_txc ,input wire reset_n ,input wire tx_start_en , //以太网开始发送信