• Java8中有哪些原子类呢?


    转自:

    Java8中有哪些原子类呢?

    下文笔者讲述原生态的jdk8的原子类(线程安全类)

    AtomicBoolean
    AtomicInteger
    AtomiclIntegerArray
    AtomiclntegerFieldUpdater
    AtomicLong
    AtomicLongArray
    AtomicLongFieldUpdater
    AtomicMarkableReference
    AtomicReference
    AtomicReferenceArray
    AtomicReferenceFieldUpdater
    AtomicStampedReference
    
    JDK8时新增了4个原子操作类
     如下:
    DoubleAccumulator
    DoubleAdder
    LongAccumulatorLongAdder
    

    Atomic包操作基本数据类型,可使用以下原子类

    AtomicBoolean:原子更新布尔类型 
    AtomicInteger:原子更新整型
    AtomicLong:原子更新长整型 
    

    这些基础类提供一些常见的方法

    int addAndGet(int delta):
       以原子的方式将输入的数值与实例中的值相加,并返回结果。 
    boolean compareAndSet(int expect, int update):
       如果输入的值等于预期值,则以原子方式将该值设置为输入的值。 
    int getAndIncrement():
       以原子的方式将当前值加 1
         注意,这里返回的是自增前的值,也就是旧值。 
    void lazySet(int newValue):
       最终会设置成newValue,使用lazySet设置值后,
        可能导致其他线程在之后的一小段时间内还是可以读到旧的
    int getAndSet(int newValue):
       以原子的方式设置为newValue,并返回旧值 
    

    	static AtomicInteger ai =new AtomicInteger(1);
    	public static void main(String[] args) {
     
    		System.out.println(ai.getAndIncrement());
    		System.out.println(ai.get());
         }
    

    getAndIncrement()实现原子操作示例分享

     public final int getAndIncrement() {
            return unsafe.getAndAddInt(this, valueOffset, 1);
        }
     
    public final int getAndAddInt(Object var1, long var2, int var4) {
            int var5;
            do {
                var5 = this.getIntVolatile(var1, var2);
            } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
     
            return var5;
        }
    
    注意事项:
      AtomicBoolean将Boolean转成整型
      然后使用compareAndSwapInt进行操作 
    /**
     * 如果当前数值是var4,则原子的将java变量更新成var5或var6
     * @return 如果更新成功返回true
     */
    public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
    public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
     

    原子更新数组

    AtomicIntegerArray:  原子更新整型数组里的元素。 
    AtomicLongArray:  原子更新长整型数组里的元素。 
    AtomicReferenceArray:  原子更新引用类型数组里的元素。
    

    以上三个类常用的方法:

      get(int index):获取索引为index的元素值。 
      compareAndSet(int i, int expect, int update): 如果当前值等于预期值,则以原子方式将数组位置 i 的元素设置为update值。 
    

    AtomicReferenceArray示例

    	static int[] value =new int[]{1,2};
    	static AtomicIntegerArray ai =new AtomicIntegerArray(value);
    	public static void main(String[] args) {
     
    		ai.getAndSet(0,2);
    		System.out.println(ai.get(0));
    		System.out.println(value[0]);
        }
    

    原子更新引用类型

    原子更新基本类型的AtomicInteger
    只能更新一个值
    如果更新多个值
      如更新一个对象里的值
     则需使用原子更新引用类型提供的类
    

    Atomic包包含以下三个类

    AtomicReference:
       原子更新引用类型
    AtomicReferenceFieldUpdater:
       原子更新引用类型的字段 
    AtomicMarkableReferce:
       原子更新带有标记位的引用类型
        可以使用构造方法更新一个布尔类型的标记位和引用类型。 
    
      public static AtomicReference ai = new AtomicReference();
     
        public static void main(String[] args) {
            User u1 = new User("java265", 22);
            ai.set(u1);
            User u2 = new User("liuliu", 19);
            ai.compareAndSet(u1, u2);
            System.out.println(ai.get().getAge() + ai.get().getName());
        }
    
    static class User {
            private String name;
            private int age;
     
            public User(String name, int age) {
                this.name = name;
                this.age = age;
            }
     
            public String getName() {
                return name;
            }
     
            public void setName(String name) {
                this.name = name;
            }
     
            public int getAge() {
                return age;
            }
     
            public void setAge(int age) {
                this.age = age;
            }
        }
     
     
    对象放于AtomicReference中
     然后调用compareAndSet()原子操作替换
     原理和 AtomicInteger相同
      调用compareAndSwapObject()方法
    

    原子更新字段类

    当需要原子的更新类里某个字段时
     需要用到原子更新字段类
      Atomic包提供了3个类进行原子字段更新:
    AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。 
    AtomicLongFieldUpdater:原子更新长整型字段的更新器。 
    AtomicStampedFieldUpdater:原子更新带有版本号的引用类型。 
     

    例:

     //创建原子更新器,并设置需要更新的对象类和对象的属性
    private static AtomicIntegerFieldUpdater ai = AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
    public static void main(String[] args) {
    	User u1 = new User("java265",22);
    	//原子更新年龄,+1
    	System.out.println(ai.getAndIncrement(u1));
    	System.out.println(u1.getAge());
    }
     
    static class User {
            private String name;
            public volatile int age;
     
            public User(String name, int age) {
                this.name = name;
                this.age = age;
            }
     
            public String getName() {
                return name;
            }
     
            public void setName(String name) {
                this.name = name;
            }
     
            public int getAge() {
                return age;
            }
     
            public void setAge(int age) {
                this.age = age;
            }
        }
    
    第一步:
       因为原子更新字段类都是抽象类,每次使用的时候必须使用静态方法newUpdater()
       创建一个更新器,并且需要设置想要更新的类和属性
    第二步:
        更新类的字段必须使用 public volatile 修饰
    

    新增原子类简介

    DoubleAccumulator
    LongAccumulator
    DoubleAdder
    LongAdder
    
     
     LongAdder是LongAccumulator的一个特例
      调用LongAdder相当使用下面的方式
        调用LongAccumulator,LongAccumulator提供了比LongAdder更强大的功能
    	构造函数其中accumulatorFunction一个双目运算器接口
    	根据输入的两个参数返回一个计算值
    	identity则是LongAccumulator累加器的初始值
    

    例:

    private static ExecutorService executorService = Executors.newFixedThreadPool(5);
        public static void main(String[] args) {
            for (int i = 1; i <= 100; i++) {
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        counter.add(2);
                    }
                });
            }
            System.out.println(counter.sum());
            System.out.println(counter);
        }
  • 相关阅读:
    systemverilog学习 ---- 类(完结)
    ChatGPT - 高效编写Prompt
    挺后悔,我敷衍地回答了“程序员如何提升抽象思维“
    nvm下载安装+使用教程(管理nodejs版本,实现按需加载版本)
    手写JS的new操作符的功能、手写实现JS中Object类的call函数、apply函数的功能
    通过Linux deploy搭建Android服务器(包括git)
    (Typora图床)阿里云oss搭建图床+Picgo上传图片详细教程
    SaaS 架构实现理论(二)多租户/高性能多租户
    华清远见(上海中心)22071
    ElementUI浅尝辄止23:Loading 加载
  • 原文地址:https://blog.csdn.net/qq_25073223/article/details/127400327