首页 > 代码库 > 普通int值在多线程下的递增操作

普通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);act答案
   // 控制主线程的辅助对象;(主线程等着所有附属线程都运行完毕再继续)
   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);
   // 创建并启动其他附属线程SAT答案
   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没有进行激进优化。托福答案 www.daan678.com
   而 AtomicInteger 效率其实也不低,10亿次消耗了80秒, 那100万次大约也就是千分之一,80毫秒的样子。

普通int值在多线程下的递增操作