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<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); }
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。