1 Atomic 原子类介绍( 三 )


3 数组类型原子类 3.1 数组类型原子类介绍
使用原子的方式更新数组里的某个元素
上面三个类提供的方法几乎相同 , 所以我们这里以为例子来介绍 。
类常用方法
public final int get(int i) //获取 index=i 位置元素的值public final int getAndSet(int i, int newValue)//返回 index=i 位置的当前的值 , 并将其设置为新值:newValuepublic final int getAndIncrement(int i)//获取 index=i 位置元素的值 , 并让该位置的元素自增public final int getAndDecrement(int i) //获取 index=i 位置元素的值 , 并让该位置的元素自减public final int getAndAdd(int i, int delta) //获取 index=i 位置元素的值 , 并加上预期的值boolean compareAndSet(int i, int expect, int update) //如果输入的数值等于预期值 , 则以原子方式将 index=i 位置的元素值设置为输入值(update)public final void lazySet(int i, int newValue)//最终 将index=i 位置的元素设置为newValue,使用 lazySet 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值 。
3.2常见方法使用
import java.util.concurrent.atomic.AtomicIntegerArray;public class AtomicIntegerArrayTest {public static void main(String[] args) {// TODO Auto-generated method stubint temvalue = http://www.kingceram.com/post/0;int[] nums = { 1, 2, 3, 4, 5, 6 };AtomicIntegerArray i = new AtomicIntegerArray(nums);for (int j = 0; j < nums.length; j++) {System.out.println(i.get(j));}temvalue = i.getAndSet(0, 2);System.out.println("temvalue:" + temvalue + ";i:" + i);temvalue = http://www.kingceram.com/post/i.getAndIncrement(0);System.out.println("temvalue:" + temvalue + ";i:" + i);temvalue = http://www.kingceram.com/post/i.getAndAdd(0, 5);System.out.println("temvalue:" + temvalue + ";i:" + i);}}
4 引用类型原子类 4.1 引用类型原子类介绍
基本类型原子类只能更新一个变量 , 如果需要原子更新多个变量 , 需要使用 引用类型原子类 。
上面三个类提供的方法几乎相同 , 所以我们这里以为例子来介绍 。
4.2类使用示例
import java.util.concurrent.atomic.AtomicReference;public class AtomicReferenceTest {public static void main(String[] args) {AtomicReference ar = new AtomicReference();Person person = new Person("SnailClimb", 22);ar.set(person);Person updatePerson = new Person("Daisy", 20);ar.compareAndSet(person, updatePerson);System.out.println(ar.get().getName());System.out.println(ar.get().getAge());}}class Person {private String name;private int age;public Person(String name, int age) {super();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;}}
上述代码首先创建了一个对象 , 然后把对象设置进对象中 , 然后调用方法 , 该方法就是通过 CAS 操作设置 ar 。如果 ar 的值为的话 , 则将其设置为。实现原理与类中的方法相同 。运行上面的代码后的输出结果如下:
Daisy20
4.3 ce 类使用示例
import java.util.concurrent.atomic.AtomicStampedReference;public class AtomicStampedReferenceDemo {public static void main(String[] args) {// 实例化、取当前值和 stamp 值final Integer initialRef = 0, initialStamp = 0;final AtomicStampedReference asr = new AtomicStampedReference<>(initialRef, initialStamp);System.out.println("currentValue="http://www.kingceram.com/post/+ asr.getReference() +", currentStamp=" + asr.getStamp());// compare and setfinal Integer newReference = 666, newStamp = 999;final boolean casResult = asr.compareAndSet(initialRef, newReference, initialStamp, newStamp);System.out.println("currentValue="http://www.kingceram.com/post/+ asr.getReference()+", currentStamp=" + asr.getStamp()+ ", casResult=" + casResult);// 获取当前的值和当前的 stamp 值int[] arr = new int[1];final Integer currentValue = http://www.kingceram.com/post/asr.get(arr);final int currentStamp = arr[0];System.out.println("currentValue="http://www.kingceram.com/post/+ currentValue +", currentStamp=" + currentStamp);// 单独设置 stamp 值final boolean attemptStampResult = asr.attemptStamp(newReference, 88);System.out.println("currentValue="http://www.kingceram.com/post/+ asr.getReference()+", currentStamp=" + asr.getStamp()+ ", attemptStampResult=" + attemptStampResult);// 重新设置当前值和 stamp 值asr.set(initialRef, initialStamp);System.out.println("currentValue="http://www.kingceram.com/post/+ asr.getReference() +", currentStamp=" + asr.getStamp());// [不推荐使用 , 除非搞清楚注释的意思了] weak compare and set// 困惑!weakCompareAndSet 这个方法最终还是调用 compareAndSet 方法 。[版本: jdk-8u191]// 但是注释上写着 "May fail spuriously and does not provide ordering guarantees,// so is only rarely an appropriate alternative to compareAndSet."// todo 感觉有可能是 jvm 通过方法名在 native 方法里面做了转发final boolean wCasResult = asr.weakCompareAndSet(initialRef, newReference, initialStamp, newStamp);System.out.println("currentValue="http://www.kingceram.com/post/+ asr.getReference()+", currentStamp=" + asr.getStamp()+ ", wCasResult=" + wCasResult);}}