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


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

  • 相关阅读:
    Nginx+uWsgi+Django+Python+MongoDB+mySQL服务器搭建
    Scott Guthrie's Blog on ASP.NET
    NPOI 读写excel
    用C#开发了一个Android 浏览器APP
    Windows 8 应用开发技术资源
    微软发布Sample Browser for Windows 8版:5000示例代码,"触手可及"
    依赖注入
    DIY 一套正版、免费、强大的 Visual Studio 2012 IDE
    基于JQuery EasyUI、Web Api的 ASP.NET MVC 代码生成插件
    深度剖析Byteart Retail案例:AOP 异常处理与缓存
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7357478.html
Copyright © 2020-2023  润新知