前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >并发编程中的原子类

并发编程中的原子类

作者头像
Dream城堡
发布2019-05-20 10:30:26
4150
发布2019-05-20 10:30:26
举报
文章被收录于专栏:Spring相关Spring相关
1.什么是原子类

一度认为原子是不可分割的最小单位,故原子类可以认为其操作都是不可分割

1.1 为什么要有原子类?

对多线程访问同一个变量,我们需要加锁,而锁是比较消耗性能的,JDk1.5之后, 新增的原子操作类提供了 一种用法简单、性能高效、线程安全地更新一个变量的方式, 这些类同样位于JUC包下的atomic包下,发展 到JDk1.8,该包下共有17个类, 囊括了原子更新基本类型、原子更新数组、原子更新属性、原子更新引用

1.2 1.8新增的原子类

DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder、Striped64

2.原子更新基本类型

发展至JDk1.8,基本类型原子类有以下几个: AtomicBoolean、AtomicInteger、AtomicLong、DoubleAccumulator、DoubleAdder、LongAccumulator、 LongAdder 大致可以归为3类 AtomicBoolean、AtomicInteger、AtomicLong 元老级的原子更新,方法几乎一模一样 DoubleAdder、 LongAdder 对Double、Long的原子更新性能进行优化提升 DoubleAccumulator、LongAccumulator 支持自定 义运算

/**
 * atomicInteger Demo
 */
public class Demo1 {

    private static AtomicInteger sum = new AtomicInteger(0);

    public static void inCreate() {

        sum.incrementAndGet();


    }


    public static void main(String[] args) throws InterruptedException {


        for (int i = 0; i < 10; i++) {
            new Thread(()->{

                for (int j = 0; j < 100; j++) {
                    inCreate();
                    System.out.println(sum);
                }
            }).start();

        }

    }
}
LongAccumulator Demo自定义运算
/**
 * LongAccumulator Demo
 * 自定义运算
 */
public class Demo2 {


    public static void main(String[] args) {

        //输入一个数字,如果比上一个输入的大,则直接返回
        //如果小则返回上一个
        LongAccumulator longAccumulator =
                new LongAccumulator((left, right) ->

//                    left > right ? left : right,
                    left+right ,
                        0L
                );
        longAccumulator.accumulate(3L);
        System.out.println(longAccumulator.get());
        longAccumulator.accumulate(5L);
        System.out.println(longAccumulator.get());
    }
}
3.原子更新数组类型

AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray

/**
 * AtomicIntegerArry  Demo
 */
public class AtomicIntegerArryDemo {

    public static void main(String[] args) {

        int[] arr = new int[]{3, 2};

        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(arr);

        //下标和步长
        int i = atomicIntegerArray.addAndGet(1, 8);
        int j = atomicIntegerArray.addAndGet(0, 8);

        System.out.println("i:" + i + "--j:" + j);

        System.out.println(  atomicIntegerArray.toString());

        //自定义运算
        /**
         *下标
         * 把下标的值更新为20
         * 相关的运算
         */
        int k = atomicIntegerArray.accumulateAndGet(
                0, 20, (left, right) ->
                        left >right?left:right
        );
        System.out.println(  atomicIntegerArray.toString());
        System.out.println("k->"+k);

    }
}
4.原子地更新属性

原子地更新某个类里的某个字段时,就需要使用原子更新字段类,Atomic包提供了以下4个类进行原子字段更新 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference、AtomicReferenceFieldUpdater

/**
 * AtomicLongFieldUpdateDemo
 */
public class AtomicLongFieldUpdaterDemo {

    static class Student {

        volatile long id;
        volatile String name;

        public Student(long id, String name) {
            this.id = id;
            this.name = name;
        }

        public long getId() {
            return id;
        }

        public void setId(long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }


    public static void main(String[] args) {
        AtomicLongFieldUpdater<Student> longFieldUpdater = AtomicLongFieldUpdater.newUpdater(Student.class, "id");

        Student testStu = new Student(1L, "test");
        longFieldUpdater.compareAndSet(testStu, 1L, 100L);

        System.out.println("id=" + testStu.getId());

        AtomicReferenceFieldUpdater<Student, String> referenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(Student.class, String.class, "name");

        referenceFieldUpdater.compareAndSet(testStu, "test", "update");
        System.out.println("name=" + testStu.getName());

    }

}
5.原子更新引用

AtomicReference:用于对引用的原子更新 AtomicMarkableReference:带版本戳的原子引用类型,版本戳为boolean类型。 AtomicStampedReference:带版本戳的原子引用类型,版本戳为int类型。

public class AtomicReferenceDemo {

    public static void main(String[] args) {
        AtomicReference<Student> studentAtomicReference = new AtomicReference<>();

        Student stuTest01 = new Student(1L, "test01");
        Student stuTest02 = new Student(2L, "test02");
        //先设置值
        studentAtomicReference.set(stuTest01);
        studentAtomicReference.compareAndSet(stuTest01,stuTest02);
        //再得到更新值
        Student studentUpd = studentAtomicReference.get();
        System.out.println(studentUpd.getName());


    }


}

class Student{

    private long id;
    private String name;

    public Student(long id, String name) {
        this.id = id;
        this.name = name;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.05.19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.什么是原子类
    • 1.1 为什么要有原子类?
      • 1.2 1.8新增的原子类
      • 2.原子更新基本类型
        • LongAccumulator Demo自定义运算
        • 3.原子更新数组类型
        • 4.原子地更新属性
        • 5.原子更新引用
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档