欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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毫秒的样子.