Java中对AtomicInteger和int值在多线程下递增操作的测试
作者:junjie 发布时间:2023-10-22 18:32:03
标签:Java,AtomicInteger,int,多线程,递增操作,测试
Java针对多线程下的数值安全计数器设计了一些类,这些类叫做原子类,其中一部分如下:
java.util.concurrent.atomic.AtomicBoolean;
java.util.concurrent.atomic.AtomicInteger;
java.util.concurrent.atomic.AtomicLong;
java.util.concurrent.atomic.AtomicReference;
下面是一个对比 AtomicInteger 与 普通 int 值在多线程下的递增测试,使用的是 junit4;
完整代码:
package test.java;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* 测试AtomicInteger与普通int值在多线程下的递增操作
*/
public class TestAtomic {
// 原子Integer递增对象
public static AtomicInteger counter_integer;// = new AtomicInteger(0);
// 一个int类型的变量
public static int count_int = 0;
@Before
public void setUp() {
// 所有测试开始之前执行初始设置工作
counter_integer = new AtomicInteger(0);
}
@Test
public void testAtomic() throws InterruptedException {
// 创建的线程数量
int threadCount = 100;
// 其他附属线程内部循环多少次
int loopCount = 10000600;
// 控制附属线程的辅助对象;(其他await的线程先等着主线程喊开始)
CountDownLatch latch_1 = new CountDownLatch(1);
// 控制主线程的辅助对象;(主线程等着所有附属线程都运行完毕再继续)
CountDownLatch latch_n = new CountDownLatch(threadCount);
// 创建并启动其他附属线程
for (int i = 0; i < threadCount; i++) {
Thread thread = new AtomicIntegerThread(latch_1, latch_n, loopCount);
thread.start();
}
long startNano = System.nanoTime();
// 让其他等待的线程统一开始
latch_1.countDown();
// 等待其他线程执行完
latch_n.await();
//
long endNano = System.nanoTime();
int sum = counter_integer.get();
//
Assert.assertEquals("sum 不等于 threadCount * loopCount,测试失败",
sum, threadCount * loopCount);
System.out.println("--------testAtomic(); 预期两者相等------------");
System.out.println("耗时: " + ((endNano - startNano) / (1000 * 1000)) + "ms");
System.out.println("threadCount = " + (threadCount) + ";");
System.out.println("loopCount = " + (loopCount) + ";");
System.out.println("sum = " + (sum) + ";");
}
@Test
public void testIntAdd() throws InterruptedException {
// 创建的线程数量
int threadCount = 100;
// 其他附属线程内部循环多少次
int loopCount = 10000600;
// 控制附属线程的辅助对象;(其他await的线程先等着主线程喊开始)
CountDownLatch latch_1 = new CountDownLatch(1);
// 控制主线程的辅助对象;(主线程等着所有附属线程都运行完毕再继续)
CountDownLatch latch_n = new CountDownLatch(threadCount);
// 创建并启动其他附属线程
for (int i = 0; i < threadCount; i++) {
Thread thread = new IntegerThread(latch_1, latch_n, loopCount);
thread.start();
}
long startNano = System.nanoTime();
// 让其他等待的线程统一开始
latch_1.countDown();
// 等待其他线程执行完
latch_n.await();
//
long endNano = System.nanoTime();
int sum = count_int;
//
Assert.assertNotEquals(
"sum 等于 threadCount * loopCount,testIntAdd()测试失败",
sum, threadCount * loopCount);
System.out.println("-------testIntAdd(); 预期两者不相等---------");
System.out.println("耗时: " + ((endNano - startNano) / (1000*1000))+ "ms");
System.out.println("threadCount = " + (threadCount) + ";");
System.out.println("loopCount = " + (loopCount) + ";");
System.out.println("sum = " + (sum) + ";");
}
// 线程
class AtomicIntegerThread extends Thread {
private CountDownLatch latch = null;
private CountDownLatch latchdown = null;
private int loopCount;
public AtomicIntegerThread(CountDownLatch latch,
CountDownLatch latchdown, int loopCount) {
this.latch = latch;
this.latchdown = latchdown;
this.loopCount = loopCount;
}
@Override
public void run() {
// 等待信号同步
try {
this.latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//
for (int i = 0; i < loopCount; i++) {
counter_integer.getAndIncrement();
}
// 通知递减1次
latchdown.countDown();
}
}
// 线程
class IntegerThread extends Thread {
private CountDownLatch latch = null;
private CountDownLatch latchdown = null;
private int loopCount;
public IntegerThread(CountDownLatch latch,
CountDownLatch latchdown, int loopCount) {
this.latch = latch;
this.latchdown = latchdown;
this.loopCount = loopCount;
}
@Override
public void run() {
// 等待信号同步
try {
this.latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//
for (int i = 0; i < loopCount; i++) {
count_int++;
}
// 通知递减1次
latchdown.countDown();
}
}
}
普通PC机上的执行结果类似如下:
--------------testAtomic(); 预期两者相等-------------------
耗时: 85366ms
threadCount = 100;
loopCount = 10000600;
sum = 1000060000;
--------------testIntAdd(); 预期两者不相等-------------------
耗时: 1406ms
threadCount = 100;
loopCount = 10000600;
sum = 119428988;
从中可以看出, AtomicInteger操作 与 int操作的效率大致相差在50-80倍上下,当然,int很不消耗时间,这个对比只是提供一个参照。
如果确定是单线程执行,那应该使用 int; 而int在多线程下的操作执行的效率还是蛮高的, 10亿次只花了1.5秒钟;
(假设CPU是 2GHZ,双核4线程,理论最大8GHZ,则每秒理论上有80亿个时钟周期,
10亿次Java的int增加消耗了1.5秒,即 120亿次运算, 算下来每次循环消耗CPU周期 12个;
个人觉得效率不错, C 语言也应该需要4个以上的时钟周期(判断,执行内部代码,自增判断,跳转)
前提是: JVM和CPU没有进行激进优化.
)
而 AtomicInteger 效率其实也不低,10亿次消耗了80秒, 那100万次大约也就是千分之一,80毫秒的样子.


猜你喜欢
- C#将对象序列化成JSON字符串public string GetJsonString() { List<Product> p
- 缘起年前,因为项目需要进行配置的优化和架构的升级,领导给我来了个任务,让我去进行技术调研需要将配置中心的yaml配置文件里面的配置转为Jso
- 本文实例讲述了C#逐行读取文件的方法。分享给大家供大家参考。具体如下:这里使用C#逐行读取文件,对于大文件的读取非常有用。StreamRea
- 工作以来,代码越写越多,程序也越来越臃肿,效率越来越低,对于我这样一个追求完美的程序员来说,这是绝对不被允许的,于是除了不断优化程序结构外,
- 导入thymeleaf<dependency> <groupId>org.springframework
- 前言现在很多的 App 都有自动轮播的 banner 界面,用于展示广告图片或者显示当前比较热门的一些活动,除了具备比较酷炫的效果之外,通过
- 现在,我们来讲一下怎么用Java来实现简单画板,要实现的功能有:选择图形(方形、圆形、多边形...)、可以选择颜色。首先,打开windows
- 本文实例讲述了C#实现客户端弹出消息框封装类。分享给大家供大家参考。具体如下:asp.net在服务器端运行,是不能在服务器端弹出对话框的,但
- 1)1、1、2、3、5、8.......用递归算法求第30位数的值?首先我们能够发现从第3位数起后一位数等于前两位数值之和,即:x=(x-1
- C++String类型的逆序这里使用反向迭代器实现#include<iostream> #include <string&
- Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。
- @RequestBody部分属性丢失问题描述JavaBean实现public class VerifyNewFriendApplyReq i
- 1.JWT定义JWT(Json Web Token)是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的
- 做Android开发的童靴们肯定对系统自带的控件使用的都非常熟悉,比如Button、TextView、ImageView等。如果你问我具体使
- 本文实例为大家分享了Android实现拍照添加时间水印的具体代码,供大家参考,具体内容如下效果如下图 :1、拍照// 非空判断 拍照?if
- 本文接上文“java反射之方法反射的基本操作方法”,利用反射了解下java集合中泛型的本质1、初始化两个集合,一个使用泛型,一个不使用Arr
- 废话目前流行的前后端分离让Java程序员可以更加专注的做好后台业务逻辑的功能实现,提供如返回Json格式的数据接口就可以。SpringBoo
- 前言新进阶的程序员可能对async、await用得比较多,却对之前的异步了解甚少。本人就是此类,因此打算回顾学习下异步的进化史。本文主要是回
- 本文实例讲述了Android TextView中文字通过SpannableString设置属性的方法。分享给大家供大家参考,具体如下:在An
- 这几天在弄后端管理系统向指定的Android