LongAdder 高性能原子计数器

在大数据处理过程,为了方便监控,需要统计数据,少不了原子计数器。为了尽量优化性能,需要采用高效的原子计数器。在jdk8中,引入了LongAddr,非常适合多线程原子计数器。与AtomicLong做了一个测试,LongAdder在多线程环境中,原子自增长性能要好很多。

为了更加清楚的了解LongAddr原理。找到几篇不错的文章:


实质是想通过多个原子锁,来替代单一锁,减少多线程对单一锁的竞争,提高并发写的能力。distributed-cache-line-counter-scalable、LongAddr、ConcurrentHashMap都是这种思想。
public class CounterPerformanceTest {
	
	private static long count = 100000000;
	private static int threads = Runtime.getRuntime().availableProcessors();
	
	private static String type = "longAdder";

	private static CountDownLatch startLatch;
	private static CountDownLatch endLatch;
	
	private static ExecutorService executorService;
	
	private static AtomicLong totalTime = new AtomicLong(0);
	
	private static AtomicLong atomicCount = new AtomicLong();
	private static LongAdder longAdder = new LongAdder();
	
	public static void main(String[] args) throws InterruptedException {
		threads = Integer.valueOf(System.getProperty("threads", String.valueOf(threads)));
		count = Long.valueOf(System.getProperty("count", String.valueOf(count)));
		type = System.getProperty("count", type);
		
		executorService = Executors.newFixedThreadPool(threads);
		startLatch = new CountDownLatch(1);
		endLatch = new CountDownLatch(threads);
		
		creatThread();
		
		startLatch.countDown();
		System.out.println("启动测试...");
		endLatch.await();
		System.out.println("Counter:" + getLong());
		
		System.out.println("测试结束...");
		System.out.println("avg time:" + totalTime.longValue()/1000/threads);
		System.out.println("tps:" + (getLong()/(totalTime.longValue()/1000/threads)));
		executorService.shutdown();
	}
	
	private static long getLong() {
		if("atomic".equals(type))
			return atomicCount.longValue();
		else if("longAdder".equals(type))
			return longAdder.longValue();
		else 
			return 0l;
	}
	
	private static void incr() {
		if("atomic".equals(type))
			atomicCount.incrementAndGet();
		else if("longAdder".equals(type))
			longAdder.increment();
	}
	
	private static void creatThread() {
		for(int i = 0; i < threads; i++) {
			executorService.submit(new Runnable() {
				public void run() {
					try {
						startLatch.await();
						long startTime = System.currentTimeMillis();
						
						for(int j=0; j<count; j++)
							incr();
						
						long time = System.currentTimeMillis() - startTime;
						totalTime.addAndGet(time);
						endLatch.countDown();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
		}
	}
}

猜你喜欢

转载自melin.iteye.com/blog/1973363