1.什么是原子操作类
就是我们一般在使用程序更新一个变量,当前变量i=1,如果两个线程都对齐i++,由于线程的竞争,可能结果为2就不是3了。而要保证线程的同步性,那么我们以前的解决办法肯定是加synchrnized关键字来保证只能有一个线程来更新操作。java提供了更高效的类:原子操作类。分为:基本类型的原子更新、数组类型的原子更新、引用类型的原子更新、属性的原子更新。
2.原子更新基本类型类
--- AtomicBoolean:原子更新布尔值类型。
--- AtomicInteger:原子更新整型。
--- AtomicLong:原子更新长整型。
实现:
public class AtomicIntegerTest {
public static void main(String[] args) {
AtomicInteger ai= new AtomicInteger(2);
int initalVal=ai.get();
System.out.println("初始化当前值a为:"+initalVal);
System.out.println("当前值a+3="+ai.addAndGet(-3));
ai.getAndIncrement();
int nextVal=ai.get();
System.out.println("加1后的当前值为:"+nextVal);
System.out.println("更新值是否等于预期值:"+ai.compareAndSet(nextVal, 10));
int updateVal=ai.get();
System.out.println("更新后的值:"+updateVal);
}
}
结果:
初始化当前值a为:2
当前值a+3=-1
加1后的当前值为:0
更新值是否等于预期值:true
更新后的值:10
注意:getAndIncrement();方法的返回值为加1之前的值。
3.原子更新数组
AtomicIntegerArray:原子更新整型数组里的元素。
AtomicLongArray:原子更新整型数组里的元素。
AtomicReferenceArray:原子更新引用类型数组里元素。
其实方法和上面原子更新基本类型大多都一样。
实现:
public class AtomicIntegerArrayTest {
public static void main(String[] args) {
int[] value=new int[]{1,2};
AtomicIntegerArray aia=new AtomicIntegerArray(value);
aia.getAndSet(0, 5);
System.out.println("数组下标0对应的原子值更新为:"+aia.get(0));
System.out.println("原数组的值:"+value[0]);
}
}
结果:
数组下标0对应的原子值更新为:5
原数组的值:1
4.原子更新引用类型
AtomicReference:原子更新引用类型。
AtomicReferenceFieldUpdater:原子更新引用类型里的字段。
AtomicMarkableReference:原子更新带有标记位的引用类型。可以原子更新一个布尔类型的标记位和引用类型。
其实方法和上面原子更新基本类型大多都一样。
实现:
public class AtomicReferenceTest {
public static void main(String[] args) {
AtomicReference<User> ar=new AtomicReference<User>();
User user=new User("张三",19);
ar.set(user);
System.out.println("当前原子姓名:"+ar.get().getName()+" ,当前原子年龄:"+ar.get().getAge());
User updateUser=new User("李四",29);
ar.set(updateUser);
System.out.println("更新原子姓名:"+ar.get().getName()+" ,更新原子年龄:"+ar.get().getAge());
}
}
class User{
private String name;
private int age;
public User(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;
}
}
结果:
当前原子姓名:张三 ,当前原子年龄:19
更新原子姓名:李四 ,更新原子年龄:29
5.原子更新字段类
AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
AtomicLongFieldUpdater:原子更新长整型字段的更新器。
AtomicStampedReference:原子更新带有版本号的引用类型。使用这个类可以将那个整数值与引用关联,可以用来以原子的方式来更新数据和数据的版本号,可以解决原子更新可能出现的ABA问题。
其实方法和上面原子更新基本类型大多都一样。
实现:
public class AtomicIntegerFieldUpdaterTest {
public static void main(String[] args) {
AtomicIntegerFieldUpdater<MyUser> aifu=AtomicIntegerFieldUpdater.newUpdater(MyUser.class, "age");
MyUser myUser=new MyUser("张三",20);
System.out.println("此时原子值为:"+aifu.getAndIncrement(myUser));
System.out.println("更新原子值为:"+aifu.get(myUser));
}
}
class MyUser{
private String name;
public volatile int age;
public MyUser(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;
}
}
结果:
此时原子值为:20
更新原子值为:21
解释:原子更新字段首先需要创建一个更新器,并且还得设置需要更新的类和属性。用作更新的属性需要使用volatile、public字段修饰。