atomic包下幾個(gè)類的用法
1.原子更新引用類型
以原子的方式更新某個(gè)引用對(duì)象,可以使用如下的類去實(shí)現(xiàn)
AtomicReference
使用過(guò)程中,更新的時(shí)候要避免錯(cuò)誤使用
/**
* 原子更新整個(gè)引用類型
* @author senninha
*
*/
public class AtomicReferenceTest {
public AtomicReference<User> user = new AtomicReference<User>(null);
public static void main(String[] args) {
// TODO Auto-generated method stub
AtomicReferenceTest t = new AtomicReferenceTest();
t.user.set(new User("senninha","21"));
User user = t.user.get();
//錯(cuò)誤的更新方法
user.setAge("10");
//正確的更新方法
user = new User("senninha","22");
t.user.set(user);
}
}
class User{
private String username;
public User(String username, String age) {
super();
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public String getAge() {
return age;
}
public void setUsername(String username) {
this.username = username;
}
public void setAge(String age) {
this.age = age;
}
private String age;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("User [username=");
builder.append(username);
builder.append(", age=");
builder.append(age);
builder.append("]");
return builder.toString();
}
}
2.帶時(shí)間戳的原子更新
避免更新時(shí)候出現(xiàn)ABA這樣的錯(cuò)誤,使用帶時(shí)間戳的原子更新方式
/**
*
*
**/
public class AtomicStampReferenceTest {
public AtomicStampedReference<User> user = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
User u = new User("senninha","21");
AtomicStampReferenceTest aft = new AtomicStampReferenceTest();
//這里可以用時(shí)間戳來(lái)表示0
aft.user = new AtomicStampedReference<User>(u, 0);
u = new User("senninha","22");
//aft.user.set(u,System.currentTimeMillis());
aft.user.set(u, aft.user.getStamp() + 1);
System.out.println(aft.user.getStamp() + " " + aft.user.getReference());
}
}
3.原子更新類中某個(gè)字段
如1那里,其實(shí)要更新的只是age字段,就可以使用原子更新某個(gè)字段的方法
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
AtomicReferenceFieldUpdater
需要把他們聲明為public volatile類型
/**
* 只更新類中的某個(gè)字段的時(shí)候
* 只需要把要更新的那個(gè)字段設(shè)置為public volatile,利用反射來(lái)實(shí)現(xiàn)CAS操作
*/
public static void atomicReferenceFieldUpdater(){
//User類中的age字段需要進(jìn)行原子操作,類型是String,字段名是age
AtomicReferenceFieldUpdater arfu = AtomicReferenceFieldUpdater.newUpdater(User.class, String.class, "age");
User u = new User("senninha","12");
arfu.compareAndSet(u, u.age, "13");
System.out.println(u.getAge());
}
}
class User{
public String username;
public volatile String age;
public User(String username, String age) {
super();
this.username = username;
this.age = age;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("User [username=");
builder.append(username);
builder.append(", age=");
builder.append(age);
builder.append("]");
return builder.toString();
}
}
4.原子更新數(shù)組
傳入后的會(huì)重新復(fù)制一份數(shù)組的拷貝,所以可以用原數(shù)組的值作為compare的比較對(duì)象.
/**
* 原子更新數(shù)組
*/
public static void atomicArrayUpdater(){
User[] user = new User[2];
user[0] = new User("senninha", "1");
user[1] = new User("senninha", "2");
AtomicReferenceArray<User> ara = new AtomicReferenceArray<User>(user);
//index,更新前的expect對(duì)象,如果expect傳入新的對(duì)象
ara.weakCompareAndSet(0, user[0], new User("senninha","3"));
System.out.println(user[0]);
System.out.println(ara.get(0));
}