追赶日月的星辰 2021-11-05 09:26 采纳率: 100%
浏览 20
已结题

【Java】LongAdder一定比AtomicLong性能要高吗

问题:
代码是《Java虚拟机-JVM故障诊断与性能优化》的,分别使用Synchronized/AtomicLong/LongAdder实现累加到TARGET_COUNT,但是最后发现无论线程数多少,LongAdder的性能都是最低的。

环境:
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b15, mixed mode)

package com.example.demo.atomic;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.IntStream;

public class AtomicLess {

    private static final int MAX_THREAD_SIZE = 3;
    private static final int MAX_TASK_SIZE = 3;
    private static final int TARGET_COUNT = 10000000;

    private AtomicLong account = new AtomicLong(0L);
    private long count = 0;
    private LongAdder longAdder = new LongAdder();

    static CountDownLatch cdlsync = new CountDownLatch(MAX_TASK_SIZE);
    static CountDownLatch cdlatomic = new CountDownLatch(MAX_TASK_SIZE);
    static CountDownLatch cdllad = new CountDownLatch(MAX_TASK_SIZE);

    protected synchronized long inc(){
        return ++count;
    }

    protected synchronized long getCount(){
        return count;
    }

    protected void clear(){
        this.count = 0;
    }

    public class SyncThread implements Runnable{

        long startTime;
        AtomicLess out;

        public SyncThread(AtomicLess out,long startTime){
            this.out = out;
            this.startTime = startTime;
        }

        @Override
        public void run() {
            long v = out.getCount();
            while (v<TARGET_COUNT){
                v = out.inc();
            }
            long endTime = System.currentTimeMillis();
            System.out.println("SyncThread Spend "+(endTime-startTime)+"ms v="+v);
            cdlsync.countDown();
        }
    }

    public class AtomicThread implements Runnable{
        long startTime;

        public AtomicThread(long startTime){
            this.startTime = startTime;
        }

        @Override
        public void run() {
            long v = account.get();
            while (v < TARGET_COUNT){
                v = account.incrementAndGet();
            }

            long endTime = System.currentTimeMillis();
            System.out.println("AtomicThread Spend "+(endTime-startTime)+"ms v="+v);
            cdlatomic.countDown();
        }
    }

    public class LongAdderThread implements Runnable{
        long startTime;

        public LongAdderThread(long startTime){
            this.startTime = startTime;
        }

        @Override
        public void run() {
            long v = longAdder.sum();
            while (v < TARGET_COUNT){
                longAdder.increment();
                v = longAdder.sum();
            }

            long endTime = System.currentTimeMillis();
            System.out.println("LongAdderThread spend "+(endTime-startTime)+"ms v="+v);
            cdllad.countDown();
        }
    }

    private void start(Runnable runnable,CountDownLatch cdl) throws InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool(MAX_THREAD_SIZE);
        IntStream.range(0,MAX_TASK_SIZE).forEach(i ->service.execute(runnable));
        cdl.await();
        service.shutdown();
    }

    /**
     * 验证使用Synchronized锁执行效率
     * 使用Executors开启{@value MAX_THREAD_SIZE}个线程
     * 循环{@value MAX_TASK_SIZE}次提交任务
     * 开启CountLatchDown等待所有任务执行完成
     * @throws InterruptedException
     */
    public void startSync() throws InterruptedException {
        start(new SyncThread(this,System.currentTimeMillis()),cdlsync);
    }

    /**
     * 验证CAS执行效率
     * @throws InterruptedException
     */
    public void startAtomic() throws InterruptedException {
        start(new AtomicThread(System.currentTimeMillis()),cdlatomic);
    }

    /**
     * 验证LongAdder的执行效率
     * @throws InterruptedException
     */
    public void startLongAdder() throws InterruptedException {
        start(new LongAdderThread(System.currentTimeMillis()),cdllad);
    }

    public static void main(String[] args) throws InterruptedException {
        AtomicLess atomicLess = new AtomicLess();
        atomicLess.startLongAdder();
        atomicLess.startSync();
        atomicLess.startAtomic();

    }

}


img

  • 写回答

1条回答 默认 最新

报告相同问题?

问题事件

  • 系统已结题 11月16日
  • 已采纳回答 11月8日
  • 创建了问题 11月5日

悬赏问题

  • ¥15 请问读取环境变量文件失败是什么原因?
  • ¥15 在若依框架下实现人脸识别
  • ¥15 网络科学导论,网络控制
  • ¥100 安卓tv程序连接SQLSERVER2008问题
  • ¥15 利用Sentinel-2和Landsat8做一个水库的长时序NDVI的对比,为什么Snetinel-2计算的结果最小值特别小,而Lansat8就很平均
  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载