Java8中有哪些原子类呢?

书欣 Java教程 发布时间:2022-11-13 23:16:46 阅读数:18828 1 并发编程面试题(2023最新版)
下文笔者讲述原生态的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<User> ai = new AtomicReference<User>();
 
    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<User> 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);
    }
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaCourse/202209/4322.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者