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次
     */
    @Test
    public 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万次
     */
    @Test
    public 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倍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/540722.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ 之 【类与对象】 从入门到精通一条龙服务 进阶篇(类的6个默认成员函数,构造,析构。。。)

以后把闹钟换成唢呐&#xff0c;醒了就起床&#xff0c;不醒就上天堂 一、类的6个默认成员函数 二、构造函数 1.概念 2.特性 三、析构函数 1.概念 2.特性 四、拷贝构造函数 1.概念 2.特征 五、赋值运算符重载 1.运算符重载 2.赋值运算符重载 3.前置和后置重载 六…

[大模型]Qwen1.5-7B-Chat FastApi 部署调用

Qwen1.5-7B-Chat FastApi 部署调用 环境准备 在 Autodl 平台中租赁一个 3090 等 24G 显存的显卡机器&#xff0c;如下图所示镜像选择 PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8&#xff08;11.3 版本以上的都可以&#xff09;。 接下来打开刚刚租用服务器的 Jupyt…

pom.xml显示灰色并被划线

在使用 IDEA 进行开发的过程中&#xff0c;有时候会遇到 pom.xml 显示灰色并被划线的情况&#xff0c;如下图&#xff1a; 这一般是因为该文件被 Maven 忽略导致的&#xff0c;可以进行如下操作恢复&#xff1a; 设置保存后&#xff0c;可以看到 pom.xml 恢复了正常&#xff1a…

使用 Java 原生或 Hutool 工具包编写非对称加解密的工具类

1、什么是非对称加密 使用一对&#xff08;2个&#xff09;密钥&#xff1a;一个用于加密信息&#xff0c;另一个则用于解密信息。有“公钥&#xff08;Public Key&#xff09;”和“私钥&#xff08;Private Key&#xff09;”之分。 非对称加密的“公钥”和“私钥”是成对出现…

Java 中文官方教程 2022 版(四十九)

原文&#xff1a;docs.oracle.com/javase/tutorial/reallybigindex.html JAXB 示例 原文&#xff1a;docs.oracle.com/javase/tutorial/jaxb/intro/examples.html 以下部分描述如何使用包含在 JAXB RI 捆绑包中的示例应用程序。JAXB RI 捆绑包可从jaxb.java.net获取。下载并安装…

基于OptiTrack跟踪系统和Turtlebot机器人的视觉SLAM定位评估

本文旨在介绍使用OptiTrack光学跟踪系统和Turtlebot机器人进行视觉SLAM定位实验的详细流程&#xff0c;包括实验平台搭建过程、数据处理过程以及SLAM估计评估方法。由于涉及知识较多&#xff0c;部分内容只给出了相关参考博文链接。 1 实验平台搭建 实验平台包括OptiTrack光学…

使用 Meltano 将数据从 Snowflake 导入到 Elasticsearch:开发者之旅

作者&#xff1a;来自 Elastic Dmitrii Burlutskii 在 Elastic 的搜索团队中&#xff0c;我们一直在探索不同的 ETL 工具以及如何利用它们将数据传输到 Elasticsearch&#xff0c;并在传输的数据上实现 AI 助力搜索。今天&#xff0c;我想与大家分享我们与 Meltano 生态系统以及…

Python项目1 外星人入侵_记分

在本章中&#xff0c;我们将结束游戏《外星人入侵》的开发。我们将添加一个Play按钮&#xff0c;用于根据需要启动游戏以及在游戏结束后重启游戏。我们还将修改这个游戏&#xff0c;使其在玩 家的等级提高时加快节奏&#xff0c;并实现一个记分系统。阅读本章后&#xff0c;你将…

2024年【山东省安全员C证】考试资料及山东省安全员C证考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 山东省安全员C证考试资料考前必练&#xff01;安全生产模拟考试一点通每个月更新山东省安全员C证考试试题题目及答案&#xff01;多做几遍&#xff0c;其实通过山东省安全员C证作业模拟考试很简单。 1、【多选题】.设…

【计算机毕业设计】人事管理系统——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

二叉搜索树--搜索二维矩阵 II

题目描述 编写一个高效的算法来搜索 m * n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,…

Python之旅(一)——常量、变量、动态类型

文章目录 Python背景知识Python用途Python的优缺点Python前景&#xff08;钱景&#xff09; 常量和表达式变量与类型变量的定义变量命名的规则变量的使用变量的类型整数 int浮点数 float字符串布尔其他(暂不介绍&#xff09; 动态类型 标黄部分是和C语言不同的部分Python背景知…

在mysql中如何更新数据呢?

如何更新一条数据&#xff1f; 在 MySQL 中&#xff0c;更新一条数据可以使用 UPDATE 语句。以下是更新一条数据的基本语法&#xff1a; UPDATE table_name SET column1 value1, column2 value2,... WHERE condition;其中&#xff1a; table_name&#xff1a;要更新的表的…

Git以及Gitlab的快速使用文档

优质博文&#xff1a;IT-BLOG-CN 安装git 【1】Windows为例&#xff0c;去百度下载安装包。或者去官网下载。安装过秳返里略过&#xff0c;一直下一步即可。丌要忉记设置环境发量。 【2】打开cmd&#xff0c;输入git –version正确输出版本后则git安装成功。 配置ssh Git和s…

测试接口时出现HttpMessageNotReadableException: Required request body is missing

问题 测试接口时出现org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing异常 原因 发送请求时没有传参数 解决办法 第一种方式: 传个参数 第二种方式&#xff1a;给个空的JSON

常见的垃圾回收器(下)

文章目录 G1ShenandoahZGC 常见垃圾回收期&#xff08;上&#xff09; G1 参数1&#xff1a; -XX:UseG1GC 打开G1的开关&#xff0c;JDK9之后默认不需要打开 参数2&#xff1a;-XX:MaxGCPauseMillis毫秒值 最大暂停的时间 回收年代和算法 ● 年轻代老年代 ● 复制算法 优点…

Sam Altman新动向!被曝公开撬金主微软的客户!

Sam Altman向大公司们推销ChatGPT企业版&#xff0c;这其中包括一些微软的客户&#xff01; 好好好&#xff01; 你小子怎么回事&#xff01;金主的客户也不放过了是吧&#xff01; 根据路透社4月12日的报道&#xff0c;OpenAI首席执行官Sam Altman本月在旧金山、纽约和伦敦举…

HTML5+CSS3小实例:荧光图标悬停效果

实例:荧光图标悬停效果 技术栈:HTML+CSS 字体图标库:font-awesome 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=d…

【Qt 学习笔记】QWidget的windowOpacity属性 | cursor属性 | font属性

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ QWidget的windowOpacity属性 | cursor属性 | font属性 文章编号&#…

抖音视频无水印采集拓客软件|视频批量下载提取工具

抖音视频无水印批量采集拓客软件助力高效营销&#xff01; 随着抖音平台的崛起&#xff0c;视频已成为各行各业进行营销的重要工具。但是&#xff0c;传统的视频下载方式往往效率低下&#xff0c;无法满足快速获取大量视频的需求。针对这一问题&#xff0c;我们开发了一款视频无…