测试AtomicInteger与普通int值在多线程下的递增操作

简介: 日期: 2014年6月10日作者: 铁锚Java针对多线程下的数值安全计数器设计了一些类,这些类叫做原子类,其中一部分如下:java.util.concurrent.atomic.AtomicBoolean;java.

日期: 2014年6月10日

作者: 铁锚

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

目录
相关文章
|
5月前
|
消息中间件 Java 数据库
【消息队列开发】 实现 VirtualHostTests 类——测试虚拟主机操作
【消息队列开发】 实现 VirtualHostTests 类——测试虚拟主机操作
|
3月前
|
Cloud Native Java 调度
项目环境测试问题之线程同步器会造成执行完任务的worker等待的情况如何解决
项目环境测试问题之线程同步器会造成执行完任务的worker等待的情况如何解决
|
3月前
|
Java 测试技术
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
47 0
|
4月前
|
SQL DataWorks 数据可视化
DataWorks操作报错合集之测试OSS数据源的连通性时,出现503 Service Temporarily Unavailable的错误,是什么导致的
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
|
5月前
|
存储 测试技术
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
54 0
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
|
5月前
|
JSON Java 测试技术
SpringBoot实用开发篇第二章(测试操作)
SpringBoot实用开发篇第二章(测试操作)
|
5月前
|
SQL DataWorks 数据处理
DataWorks操作报错合集之在创建ES的数据源时,测试连通性提示无法连通,出现报错,如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
|
5月前
|
消息中间件 Java 测试技术
【消息队列开发】 测试MessageFileManager(对硬盘中的消息操作)类
【消息队列开发】 测试MessageFileManager(对硬盘中的消息操作)类
|
5月前
|
安全 Java
如何测试map对象的线程不安全
【6月更文挑战第20天】如何测试map对象的线程不安全
40 0
|
5月前
|
数据采集 SQL 分布式计算
DataWorks操作报错合集之在执行离线同步时,如果测试连接突然报错并出现类似于“exception occurs:path=[/di/testDetailConnectivity]”,如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。