突击并发编程JUC系列-数组类型AtomicLongArray

突击并发编程JUC系列演示代码地址:
https://github.com/mtcarpenter/JavaTutorial

上一个章节我们学习原子更新基本类型类,如果没有印象的小伙伴可以通过底部的链接回头看下,本章节主要介绍原子更新数组类型。

数组类型

数组类型就是通过原子的方式更新数组里的某个元素,Atomic包提供了以下 3 个类。

AtomicLongArray 常用方法如下

方法名 说明
long getAndIncrement(int i) 以原子方式将位置i处的元素原子设置为给定值,并返回旧值。
long incrementAndGet(int i) 以原子方式将索引i处以原子方式自增元素,并返回增加之后的值。
long getAndDecrement(int i) 以原子方式将索引i处的元素原子并自减1,并返回旧值。
long decrementAndGet(int i) 以原子方式将索引i处的元素原子并自减1,并返回增加之后的值。
long addAndGet(int i, long delta) 以原子方式将输入值与数组中索引i的元素相加。
long getAndSet(int i, long newValue) 将位置i处的元素原子设置为给定值,并返回旧值。
long getAndIncrement(int i) 原子地将给定的值添加到索引i的元素。
long get(int i) 获取位置i的当前值。
void lazySet(int i, long newValue) 最终将位置i处的元素设置为给定值。
int length() 返回数组的长度。
void set(int i, long newValue) 将位置i处的元素设置为给定值。
boolean compareAndSet(int i,int expect,int update) 如果当前值==预期值,则以原子方式将数组位置i的元素设置成update值。
boolean weakCompareAndSet(int i, int expect, long update) 如果当前值==期望值,则将位置i处的元素原子设置为给定的更新值。
........ ........
JDK 1.8 新增
long getAndUpdate(int i, LongUnaryOperator updateFunction) 使用将给定函数应用给当前值和给定值的结果原子更新当前值,返回旧值
long updateAndGet(int i, LongUnaryOperator updateFunction) 使用将给定函数应用给当前值和给定值的结果原子更新当前值,返回新值
........

小试牛刀

指定大小

public class AtomicExample4 {
    /**
     * 初始化 数组长度为 10
     */
    private static AtomicLongArray arr = new AtomicLongArray(5);

    private static LongUnaryOperator longUnaryOperator = new LongUnaryOperator() {
        @Override
        public long applyAsLong(long operand) {
            // 当前索引 + 10
            return operand + 10;
        }

    };

    private static LongBinaryOperator accumulatorFunction = new LongBinaryOperator() {

        @Override
        public long applyAsLong(long left, long right) {
            return left + right;
        }
    };

    public static void main(String[] args) {
        for (int i = 0; i < arr.length(); i++) {
            System.out.println("i-" + i + "=" + arr.get(i));
        }

        // 以原子方式给当前索引下标为(0)值加1,返回新值 (i++): 0
        System.out.println("索引 0 incrementAndGet=" + arr.getAndIncrement(0));
        // 以原子方式给当前索引下标为(0)值加1,,返回新值(++i)  两次增加 : 2
        System.out.println("索引 0 incrementAndGet=" + arr.incrementAndGet(0));
        //以原子方式给当前索引下标为(0)值减少 1,返回旧值 (i--):2
        System.out.println("索引 0 incrementAndGet=" + arr.getAndDecrement(0));
        //以原子方式给当前索引下标为(0)值减少 1,返回旧值 (--i):0
        System.out.println("索引 0 incrementAndGet=" + arr.decrementAndGet(0));
        // 以原子方式将输入的数值与实例中的值(AtomicLongArray(0)里的value)相加,并返回结果 : 100
        System.out.println("索引 0 addAndGet=" + arr.addAndGet(0, 100));
        // 获取 AtomicLongArray 的 value 100
        System.out.println("索引 0 get=" + arr.get(0));

        System.out.println("*********** JDK 1.8 ***********");
        //使用将给定函数应用给当前值和给定值的结果原子更新当前值,返回上一个值
        // 索引下标为 0 执行指定函数 结果为 100 + 10
        System.out.println("索引 0 getAndUpdate=" + arr.updateAndGet(0, longUnaryOperator));
        // 索引下标为 1 执行指定函数 结果为 0 + 10
        System.out.println("索引 1 getAndUpdate=" + arr.updateAndGet(1, longUnaryOperator));
        // 使用给定函数应用给指定下标和给定值的结果原子更新当前值,并返回结果 20
        System.out.println("索引 1 accumulateAndGet=" + arr.accumulateAndGet(1, 10, accumulatorFunction));

    }


}

运行结果如下:

i-0=0
i-1=0
i-2=0
i-3=0
i-4=0
索引 0 incrementAndGet=0
索引 0 incrementAndGet=2
索引 0 incrementAndGet=2
索引 0 incrementAndGet=0
索引 0 addAndGet=100
索引 0 get=100
*********** JDK 1.8 ***********
索引 0 getAndUpdate=110
索引 1 getAndUpdate=10
索引 1 accumulateAndGet=20

通过数组

public class AtomicExample5 {


    public static void main(String[] args) {
        /**
         * 初始化 数组
         */
        long arrs[] = {5, 20, 30, 40, 50};
        /**
         * 将初始化数组的值 赋值给 AtomicLongArray
         */
        AtomicLongArray arr = new AtomicLongArray(arrs);

        System.out.println("arr length=" + arr.length());
        for (int i = 0; i < arr.length(); i++) {
            System.out.println("i-" + i + "=" + arr.get(i));
        }

        // 通过set 给指定元素赋值
        arr.set(0, 10);
        // 通过 get 获取下标为 0 的值
        System.out.println("索引 0 get = " + arr.get(0));

        //如果"指定索引的值" =  "预期值" 就将指定的值更新为需要"更新的值"
        // 索引为 2 如果是 20 则相等,将值更新为 30
        arr.compareAndSet(2, 30, 300);
        System.out.println("compareAndSet 更新索引 2 的值= " + arr.get(2));
        // 与 compareAndSet  不管初始值是否为预期值都可能会无法更新该值。
        arr.weakCompareAndSet(2, 300, 3000);
        System.out.println("weakCompareAndSet 更新索引 2 的值= " + arr.get(2));


    }


}
  • 注意知识
    • compareAndSet : 指定 索引值 和给定 预期值 如果相等,则修改值为 更新值 .
    • weakCompareAndSet : 此方法跟compareAndSet类似,但是不管初始值是否为预期值都可能会无法更新该值。

运行结果如下:

arr length=5
i-0=5
i-1=20
i-2=30
i-3=40
i-4=50
索引 0 get = 10
compareAndSet 更新索引 2 的值= 300
weakCompareAndSet 更新索引 2 的值= 3000

总结

通过原子的方式更新数组里的某个元素,Atomic包提供了 3 个类,  AtomicIntegerArray 、 AtomicLongArray 、 AtomicReferenceArray  ,基本实现类似,在生活中使用频率比较少,如果看过上一个章节的小伙伴应该对此章节的案例相对就是轻车熟路,还不是很熟悉的小伙伴,建议尝试在电脑中运行案例,或者自己编码实现。


欢迎关注公众号 山间木匠 , 我是小春哥,从事 Java 后端开发,会一点前端、通过持续输出系列技术文章与文会友,如果本文能为您提供帮助,欢迎大家关注、在看、 点赞、分享支持,我们下期再见!

欢迎关注-1.jpg

posted @ 2020-09-23 20:46  山间木匠  阅读(229)  评论(2编辑  收藏  举报