Java中对AtomicInteger和int值在多线程下递增操作的测试
程序员文章站
2024-03-01 11:43:22
java针对多线程下的数值安全计数器设计了一些类,这些类叫做原子类,其中一部分如下:
java.util.concurrent.atomic.atomicbo...
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毫秒的样子.