LongAccumulator结果不准确及2个其他疑问

来源:6-9 功能升级

丨木頭丶吅

2022-06-30

本来是看了问答区伙伴的for比线程池快,想也复现一次,然后发现for确实是快些,但是两种方式计算的结果多次运行都不对,在LongAdder的结果倒是对的。

public class LongAccumulatorDemo_6 {
    public static void main(String[] args) throws InterruptedException {
        LongAccumulator accumulator = new LongAccumulator(getFunction(), 1);
        for (int i = 0; i < 5; i++) {
            accMethod(accumulator);
            foriMethod(accumulator);
            Thread.sleep(500);
        }
    }

    private static void foriMethod(LongAccumulator accumulator) {
        long s = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            accumulator.accumulate(i);
        }
        long e = System.currentTimeMillis();
        System.out.println("fori耗时:" + (e - s));
        System.out.println(accumulator.getThenReset());
    }

    private static void accMethod(LongAccumulator accumulator) {
        ExecutorService service = Executors.newFixedThreadPool(8);
        long start = System.currentTimeMillis();
        IntStream.range(0, 10000).forEach(i -> service.execute(() -> accumulator.accumulate(i)));
        service.shutdown();
        while (!service.isTerminated()) {

        }
        long end = System.currentTimeMillis();
        System.out.println("LongAccumulator耗时:" + (end - start));
        System.out.println(accumulator.getThenReset());
    }

    private static LongBinaryOperator getFunction() {
        return (x, y) -> x + y;
//        return (x, y) -> x * y;
//        return (x, y) -> Math.max(x,y);
    }
}

输出

LongAccumulator耗时:23
49995001
fori耗时:1
49995003
LongAccumulator耗时:14
49995003
fori耗时:0
49995003
LongAccumulator耗时:7
49995003
fori耗时:1
49995003
LongAccumulator耗时:7
49995003
fori耗时:1
49995003
LongAccumulator耗时:8
49995003
fori耗时:0
49995005

以及在

中,您说用LongAccumulator查询数据库,会发现线程池速度明显比for循环快。用线程池查数据库我见过,用LongAccumulator+线程池查数据库有例子吗?

写回答

1回答

悟空

2022-06-30

1、计算结果不正确,是因为不应重用accumulator实例,可以试一下:

for (int i = 0; i < 5; i++) {
            LongAccumulator accumulator = new LongAccumulator(getFunction(), 1);
            accMethod(accumulator);
            accumulator = new LongAccumulator(getFunction(), 1);
 
            foriMethod(accumulator);
            Thread.sleep(500);
        }


2、我指的不是用LongAccumulator+线程池查数据库哈,我指的是,用线程池比单线程for循环查询数据库,更快。

3、“还有个关于LongAdder sum()的疑问”,我觉得你的理解是对的。

0
5
悟空
回复
丨木頭丶吅
getAndSetBase做了reset
2022-07-01
共5条回复

深度解密Java并发工具,精通JUC,成为并发多面手

JUC全方位讲解,构建并发工具类知识体系

1599 学习 · 573 问题

查看课程