为了更加清楚的了解LongAddr原理。找到几篇不错的文章:
- http://minddotout.wordpress.com/2013/05/11/java-8-concurrency-longadder/
- http://concurrencyfreaks.blogspot.com/2013/09/longadder-and-dclc.html
- http://psy-lob-saw.blogspot.co.uk/2013/06/java-concurrent-counters-by-numbers.html
- http://concurrencyfreaks.blogspot.com/2013/09/distributed-cache-line-counter-scalable.html
实质是想通过多个原子锁,来替代单一锁,减少多线程对单一锁的竞争,提高并发写的能力。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(); } } }); } } }