请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

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

本来是看了问答区伙伴的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回答

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 回复 有任何疑惑可以回复我~
  • 提问者 丨木頭丶吅 #1
    感谢老师。
    1、按照您说的重新实例化后,结果正确了。但是为什么不重新实例化会出现这种问题呢?accumulator.getThenReset()的时候,应该已经重置累加器的数据了。
    3、看到在另一篇问答里您给我的回复了,编辑的时候把问题3给删除了。
    确认一下是否结论是:已遍历到的cell被修改了,sum()结果偏小;没有遍历到的cell增大了,sum()结果不受影响
    回复 有任何疑惑可以回复我~ 2022-06-30 15:40:19
  • 悟空 回复 提问者 丨木頭丶吅 #2
    1、我猜测应该是getThenReset需要一定的时间才能执行完成,在此期间不是线程安全的?2、我觉得可以总结为已遍历过的如果被修改,那么这部分差值对导致结果不准确。
    回复 有任何疑惑可以回复我~ 2022-06-30 18:56:59
  • 提问者 丨木頭丶吅 #3
    非常感谢!
    回复 有任何疑惑可以回复我~ 2022-07-01 10:20:33
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号