AtomicReference、AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater等类的使用

/ 多线程 / 没有评论 / 305浏览

AtomicReference类的作用是以原子的方式更新引用类型。下面我们看一下具体的例子。

/**
* 用户登录
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {

private String username;
private String password;

public Userinfo(String username, String password) {
this.username = username;
this.password = password;
}

public Userinfo() {
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}
/**
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 13:35
* @since 1.0.0
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
AtomicReference<Userinfo> atomic = new AtomicReference<Userinfo>();
Userinfo userinfo = new Userinfo("admin", "administrator");
atomic.set(userinfo);
Userinfo update = new Userinfo("user", "123456");
System.out.println(String.format("%s\t%s", atomic.get().getUsername(), atomic.get().getPassword()));
atomic.compareAndSet(userinfo, update);
System.out.println(String.format("%s\t%s", atomic.get().getUsername(), atomic.get().getPassword()));
}
}
admin	administrator
user	123456

下面我们看一下AtomicReferenceFieldUpdater类的使用,我们有时不想更新对象的所有属性,只想更新某一个字段,并且我们知道字段的返回值类型也有可能是不确定的,所以Java并发工具包里为我们提供了很多字段的更新类型。如AtomicIntegerFieldUpdater类和AtomicLongFieldUpdater类,前者就是更新Integer类型的字段后者就是更新Long类型字段的。除此之外我们还知道字段的类型还可能是引用类型,那我们就可以用AtomicReferenceFieldUpdater类来更新某一个引用类型的字段,这几个更新字段的类的使用方法几乎一样,所以下面只演示AtomicReferenceFieldUpdater类的使用,并且用String类型来演示。

/**
* 用户登录
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {

public volatile String username;
private String password;

public Userinfo(String username, String password) {
this.username = username;
this.password = password;
}

public Userinfo() {
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}
/**
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-20 13:35
* @since 1.0.0
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
AtomicReferenceFieldUpdater<Userinfo, String> atomic = AtomicReferenceFieldUpdater.newUpdater(Userinfo.class, String.class, "username");
Userinfo userinfo = new Userinfo("admin", "administrator");
System.out.println(atomic.get(userinfo));
System.out.println(atomic.compareAndSet(userinfo, "admin", "管理员"));
System.out.println(atomic.get(userinfo));
}
}
admin
true
管理员

这里有二点要注意:

Exception in thread "main" java.lang.IllegalArgumentException: Must be volatile type
	at java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl.<init>(AtomicReferenceFieldUpdater.java:228)
	at java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdater.java:95)
	at Test.main(Test.java:13)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalAccessException: Class Test can not access a member of class Userinfo with modifiers "private"
	at java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:284)
	at java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdater.java:76)
	at Test.main(Test.java:11)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.IllegalAccessException: Class Test can not access a member of class Userinfo with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:109)
	at sun.reflect.misc.ReflectUtil.ensureMemberAccess(ReflectUtil.java:103)
	at java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:280)
	... 7 more

下面我们看一下AtomicIntegerFieldUpdater类的使用,它比AtomicReferenceFieldUpdater类简单了一点。

public class Userinfo {

public String username;
private String password;
public volatile int age;

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public Userinfo(String username, String password, int age) {
this.username = username;
this.password = password;
this.age = age;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
AtomicIntegerFieldUpdater<Userinfo> atomic = AtomicIntegerFieldUpdater.newUpdater(Userinfo.class, "age");
Userinfo userinfo = new Userinfo("admin", "administrator", 17);
System.out.println(atomic.get(userinfo));
atomic.getAndIncrement(userinfo);
atomic.weakCompareAndSet(userinfo,18, 20);
System.out.println(atomic.get(userinfo));
}
}
17
20