Java多线程中的原子类属性说明

 更新时间:2023年10月24日 08:53:33   作者:ruan_luqingnian  
这篇文章主要介绍了Java多线程中的原子类属性说明,对多线程访问同一个变量,我们需要加锁,而锁是比较消耗性能的,JDk1.5之后,新增的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式,需要的朋友可以参考下

什么是原子类

什么是原子类

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

为什么要有原子类

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

java8新增原子类

DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder、Striped64

package 多线程.atomic.demo1;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: ruan
 * Date: 2021/7/4 12:09
 * @Description:
 */
public class Demo1 {
    private static AtomicInteger sum = new AtomicInteger(0);

    public static void inCreat(){
        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++) {
                    inCreat();
                    System.out.println(sum);
                    try {
                        Thread.sleep(200l);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        }
    }
}

原子更新基本类型

发展至JDk1.8,基本类型原子类有以下几个:

AtomicBoolean、AtomicInteger、AtomicLong、DoubleAccumulator、DoubleAdder、LongAccumulator、LongAdder

大致可以归为3类

  • AtomicBoolean、AtomicInteger、AtomicLong 元老级的原子更新,方法几乎一模一样
  • DoubleAdder、LongAdder 对Double、Long的原子更新性能进行优化提升
  • DoubleAccumulator、LongAccumulator 支持自定义运算
package 多线程.atomic.demo1;

import java.util.concurrent.atomic.LongAccumulator;

/**
 * @Author: ruan
 * Date: 2021/7/4 12:20
 * @Description:
 */
public class Demo2 {
    public static void main(String[] args) {
        LongAccumulator longAccumulator = new LongAccumulator((left,right)->
                left > right ? left : right,0L
                );
        longAccumulator.accumulate(3l);
        System.out.println(longAccumulator.get());
    }
}

原子更新数组类型

AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray

package 多线程.atomic.demo2;

import java.util.concurrent.atomic.AtomicIntegerArray;

/**
 * @Author: ruan
 * Date: 2021/7/4 12:26
 * @Description:
 */
public class Demo1 {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5};
        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(arr);
        int i = atomicIntegerArray.addAndGet(1, 2);
        System.out.println(i);
        //自定义计算
        int i1 = atomicIntegerArray.accumulateAndGet(0, 2, ((left, right) ->
                left > right ? left : right
        ));

        System.out.println(i1);
    }
}

原子更新属性

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

AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReference、AtomicReferenceFieldUpdater

使用上述类的时候,必须遵循以下原则

  • 字段必须是volatile类型的,在线程之间共享变量时保证立即可见
  • 字段的描述类型是与调用者与操作对象字段的关系一致。
  • 也就是说调用者能够直接操作对象字段,那么就可以反射进行原子操作。
  • 对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。
  • 只能是实例变量,不能是类变量,也就是说不能加static关键字。
  • 只能是可修改变量,不能使final变量,因为final的语义就是不可修改。
  • 对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。
  • 如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。
package 多线程.atomic.demo3;

import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

/**
 * @Author: ruan
 * Date: 2021/7/4 12:48
 * @Description:
 */
public class Demo1 {
    public static void main(String[] args) {
        Student student = new Student("ruan", 18L);
        AtomicLongFieldUpdater<Student> longFieldUpdater = AtomicLongFieldUpdater.newUpdater(Student.class, "age");
        longFieldUpdater.compareAndSet(student,18L,20L);
        System.out.println("age = " + student.getAge());
        AtomicReferenceFieldUpdater<Student, String> objectObjectAtomicReferenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(Student.class,String.class,"name");
        objectObjectAtomicReferenceFieldUpdater.compareAndSet(student,"ruan","ruanxiangge");
        System.out.println("name = " + student.getName());

    }
}
class Student{
    volatile String name;
    volatile long age;

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

    public String getName() {
        return name;
    }

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

    public long getAge() {
        return age;
    }

    public void setAge(long age) {
        this.age = age;
    }
}

原子更新引用

  • AtomicReference:用于对引用的原子更新
  • AtomicMarkableReference:带版本戳的原子引用类型,版本戳为boolean类型。
  • AtomicStampedReference:带版本戳的原子引用类型,版本戳为int类型。
package 多线程.atomic.demo4;

import java.util.concurrent.atomic.AtomicReference;

/**
 * @Author: ruan
 * Date: 2021/7/4 13:03
 * @Description:
 */
public class Demo1 {
    public static void main(String[] args) {
        AtomicReference<Student> studentAtomicReference = new AtomicReference<>();
        Student ruan = new Student(1L, "ruan");
        Student rxg = new Student(2L, "rxg");
        studentAtomicReference.set(ruan );
        boolean b = studentAtomicReference.compareAndSet(ruan, rxg);
        Student student = studentAtomicReference.get();
        System.out.println(student.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;
    }
}

到此这篇关于Java多线程中的原子类属性说明的文章就介绍到这了,更多相关Java原子类属性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java Proxy机制详细解读

    Java Proxy机制详细解读

    这篇文章主要介绍了Java Proxy机制详细解读,还是非常不错的,这里分享给大家,需要的朋友可以参考下。
    2017-10-10
  • IDEA报错之前言中不允许有内容问题及解决

    IDEA报错之前言中不允许有内容问题及解决

    当使用IntelliJ IDEA时,可能会遇到报错信息“前言中不允许有内容”,这通常是由于XML文件是以带有BOM头的UTF-8格式保存的,导致IDE的解析出错,解决办法是在IDEA中调整文件编码设置为无BOM的UTF-8,然后用文本编辑器(如Notepad++)
    2024-10-10
  • 在jmeter的beanshell中用java获取系统当前时间的简单实例

    在jmeter的beanshell中用java获取系统当前时间的简单实例

    这篇文章介绍了在jmeter的beanshell中用java获取系统当前时间的简单实例,有需要的朋友可以参考一下
    2013-09-09
  • java实现雷霆战机

    java实现雷霆战机

    这篇文章主要为大家详细介绍了java实现雷霆战机,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • redisson分布式限流RRateLimiter源码解析

    redisson分布式限流RRateLimiter源码解析

    这篇文章主要为大家介绍了redisson分布式限流RRateLimiter源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • 关于java String中intern的深入讲解

    关于java String中intern的深入讲解

    这篇文章主要给大家介绍了关于java String中intern的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-04-04
  • SpringCloud Alibaba 基本开发框架搭建过程

    SpringCloud Alibaba 基本开发框架搭建过程

    这篇文章主要介绍了SpringCloud Alibaba 基本开发框架搭建过程,开发工具选用的idea,本文通过图文实例相结合给大家分享搭建全过程,需要的朋友可以参考下
    2021-06-06
  • SpringBoot集成企业微信开发的实现

    SpringBoot集成企业微信开发的实现

    本文将详细介绍如何使用 Spring Boot 集成企业微信开发,通过企业微信 API 可以实现企业内部的一些自动化业务流程,提高工作效率,感兴趣的可以了解一下
    2023-07-07
  • 使用java -jar修改SpringBoot中application.properties的配置项

    使用java -jar修改SpringBoot中application.properties的配置项

    这篇文章主要介绍了使用java -jar修改SpringBoot中application.properties的配置项问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Lombok的@Accessors使用说明

    Lombok的@Accessors使用说明

    这篇文章主要介绍了Lombok的@Accessors使用说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03

最新评论