• 并发编程中的原子类


    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;
        }
    }
    
  • 相关阅读:
    FIREDAC(DELPHI10 or 10.1)提交数据给ORACLE数据库的一个不是BUG的BUG
    分布式系统的软肋——数据一致性
    原子操作
    Android---观察者模式的简单实现demo
    Android -- 获取网络数据并将数据存到本地数据库中
    加密模式
    Vue.js——vue-resource全攻略
    VUE---Missing space before function parentheses
    css:子元素div 上下左右居中方法总结
    扒取网站的源代码
  • 原文地址:https://www.cnblogs.com/charlypage/p/10890501.html
Copyright © 2020-2023  润新知