美文网首页
LongAccumulator类的BUG——reset方法并不能

LongAccumulator类的BUG——reset方法并不能

作者: 卡斯特梅的雨伞 | 来源:发表于2020-09-11 11:39 被阅读0次

LongAccumulator.reset方法并不能重置LongAccumulator的identity:初始值正确,使其恢复原来的初始值。当初始值为0是不会发生这个问题,而当我们设置初始值如1时,就会导致后续的计算操作增加了5份初始值,目前猜测原因是因为代码中LongAccumulator在并发量比较大的情况下,操作数据的时候,相当于把这个数字分成了很多份数字 ,而初始化的时候也是初始化了多份数据,导致初始值叠加了多份。不知道这是个bug么?待解惑。

在此记录下来希望有遇到这种情况的同学注意。解决方法便是要么初始值identity=0不会有这种问题;或者有需要使用reset方法重置的改为重新创建个LongAccumulator处理。

源码:

public void reset() {
    Cell[] as = cells; Cell a;
    base = identity;
    if (as != null) {
        for (int i = 0; i < as.length; ++i) {
            if ((a = as[i]) != null)
                //对多个cell进行初始值赋值导致后面计算叠加了多份初始值
                a.value = identity;
        }
    }
}

示例:

public class LongAccumulatorTest {
    //设置初始值为1查看输出结果
    private static volatile LongAccumulator count = new LongAccumulator((x, y) -> x + y, 1);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 5; i++) {
            count.reset();
            averageTest();
        }
    }

    public static void averageTest() throws InterruptedException {
        long t1 = System.currentTimeMillis();
        //自定义包含策略
        ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50, 60,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>(5),
                new DemoThreadFactory("订单创建组"), new ThreadPoolExecutor.AbortPolicy());
        CountDownLatch latch = new CountDownLatch(50);
        for (int i = 0; i < 50; i++) {
            executor.execute(() -> {
                try {
                    for (int j = 0; j < 1000000; j++) {
                        count.accumulate(1);
                    }
                } finally {
                    latch.countDown();
                }

            });
        }
        latch.await();
        long t2 = System.currentTimeMillis();
        System.out.println(String.format("结果:%s,耗时(ms):%s", count.longValue(), (t2 - t1)));
        executor.shutdown();
    }
}

输出:这时候你会发现只有第一次计算是正确的,只要使用了rest方法重置就会导致这个错误。

结果:50000001,耗时(ms):185
结果:50000005,耗时(ms):143
结果:50000005,耗时(ms):139
结果:50000005,耗时(ms):162
结果:50000005,耗时(ms):142

相关文章

  • LongAccumulator类的BUG——reset方法并不能

    LongAccumulator.reset方法并不能重置LongAccumulator的identity:初始值正...

  • JDK8中新增原子性操作类LongAccumulator

    一、 LongAccumulator类原理探究 LongAdder类是LongAccumulator的一个特例,L...

  • [Java]重学Java-LongAccumulator 类

    LongAccumulator LongAdder类是LongAccumulator的一个特例,它提供给用户一个自...

  • jquery重置form表单!

    form 自带reset按钮并不能真正重置表单,当表单有默认值时。所以写js方法调用,来清空form表单。

  • 原子操作类-LongAdder、LongAccumulator、

    1.Striped64 该类维护一个原子更新变量的延迟初始化表,以及一个额外的"base"域。表大小为2的幂。索引...

  • JavaScript

    定义方法方式 调用方法 清除所有属性 reset为HTML DOM中的方法,reset() 方法可把表单中的元素重...

  • git 回退

    git 回退的两种方法:回退(reset)、反做(revert) 方法一:git reset 原理: git re...

  • Android热修复之dex修复原理

    Android热修复之dex修复原理 首先有一个出Bug的类 然后在点击按钮事件里面添加调用bug类的方法 模拟b...

  • allure-10-关联Bug

    一、装饰器 二、标记 1个测试用例可以有多个bug bug可以只写地址 bug可以只写名称 支持继承,方法继承类上...

  • bug定级标准

    bug类型: 功能类、界面类、性能类、稳定性类、兼容类 bug定级: 阻塞bug: 1、常规操作引起的系统崩溃、死...

网友评论

      本文标题:LongAccumulator类的BUG——reset方法并不能

      本文链接:https://www.haomeiwen.com/subject/aabvektx.html