Adder累加器是在Jdk8引入的,AtomicLong的效率比较低,所以引入了LongAdder,为了提高并发情况下的效率。
当竞争比较激烈的时候,LongAdder可以把不同的线程对应到不同Cell上进行修改,降低了冲突的概率,采用的是多段锁的理念,提高了并发的性能。
下面我演示下LongAdder的性能。
实例代码
下面我们演示下高并发场景下LongAdder的性能大于AtomicLong,分别1万个线程,各个线程执行1万次。
实例代码如下
package com.yang.atomic; import java.awt.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.LongAdder; /** * 本实例测试LongAdder 和AtomicLong的性能 * 我们启用16个线程 * 提交10000个任务 * 每个任务累加10000次 */ public class LongAdderAndAtomicLongTest { private static AtomicLong atomicLong = new AtomicLong(); private static LongAdder longAdder = new LongAdder(); public static void main(String[] args) { //AtomicLong 线程池 ExecutorService executorService = Executors.newFixedThreadPool(20); long beginAtomicLongMills = System.currentTimeMillis(); AtomicLongRunnable atomicLongRunnable = new AtomicLongRunnable(atomicLong); for (int i = 0; i < 10000; i++) { executorService.submit(atomicLongRunnable); } executorService.shutdown(); while (!executorService.isTerminated()) { } System.out.println("执行:" + atomicLong.get() + "AtomicLong多线程累加耗时:" + (System.currentTimeMillis() - beginAtomicLongMills)); //LongAdder 线程池 executorService = Executors.newFixedThreadPool(20); beginAtomicLongMills = System.currentTimeMillis(); LongAdderRunnable longAdderRunnable = new LongAdderRunnable(longAdder); for (int i = 0; i < 10000; i++) { executorService.submit(longAdderRunnable); } executorService.shutdown(); while (!executorService.isTerminated()) { } System.out.println("执行:" + atomicLong.get() + "LongAdder多线程累加耗时:" + (System.currentTimeMillis() - beginAtomicLongMills)); } } class LongAdderRunnable implements Runnable { private LongAdder longAdder; public LongAdderRunnable(LongAdder longAdder) { this.longAdder = longAdder; } @Override public void run() { for (int i = 0; i < 10000; i++) { this.longAdder.increment(); } } } class AtomicLongRunnable implements Runnable { private AtomicLong atomicLong; public AtomicLongRunnable(AtomicLong atomicLong) { this.atomicLong = atomicLong; } @Override public void run() { for (int i = 0; i < 10000; i++) { this.atomicLong.getAndIncrement(); } } }
从运行结果中我们发现LongAdder在多线程情况下比AtomicLong要好多的。见下图。