在閱讀《實戰Java高併發程序設計》一書的4.4.7讓普通變量也享受原子操作:AtomicIntegerFieldUpdater使用的demo代碼如下:
/**
* @author 周寧
* @Date 2020-01-03 14:01
*/
public class AtomicIntegerFieldUpdaterDemo {
public static class Candidate {
int id;
volatile int score = 0;
AtomicInteger score2 = new AtomicInteger();
}
public static final AtomicIntegerFieldUpdater<Candidate> scoreUpdater =
AtomicIntegerFieldUpdater.newUpdater(Candidate.class, "score");
public static AtomicInteger realScore = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
final Candidate candidate = new Candidate();
Thread[] t = new Thread[10000];
for (int i = 0; i < 10000; i++) {
t[i] = new Thread() {
@Override
public void run() {
if (Math.random() > 0.4) {
candidate.score2.incrementAndGet();
scoreUpdater.incrementAndGet(candidate);
realScore.incrementAndGet();
}
}
};
t[i].start();
}
for (int i = 0; i < 10000; i++) {
t[i].join();
}
System.out.println("AtomicIntegerFieldUpdater Score=" + candidate.score);
System.out.println("AtomicInteger Score=" + candidate.score2.get());
System.out.println("realScore=" + realScore.get());
}
}
控制檯輸出如下:
AtomicIntegerFieldUpdater Score=5897
AtomicInteger Score=5897
realScore=5897
通過上述代碼我們不難得知使用AtomicIntegerFieldUpdater與AtomicInteger其實效果是一致的,那既然已經存在了AtomicInteger併發之神又要寫一個AtomicIntegerFieldUpdater呢?
- 1.從AtomicIntegerFieldUpdaterDemo代碼中我們不難發現,通過AtomicIntegerFieldUpdater更新score我們獲取最後的int值時相較於AtomicInteger來說不需要調用get()方法!
- 2.對於AtomicIntegerFieldUpdaterDemo類的AtomicIntegerFieldUpdater是static final類型也就是說即使創建了100個對象AtomicIntegerField也只存在一個不會佔用對象的內存,但是AtomicInteger會創建多個AtomicInteger對象,佔用的內存比AtomicIntegerFieldUpdater大,所以對於熟悉dubbo源碼的人都知道,dubbo有個實現輪詢負載均衡策略的類AtomicPositiveInteger用的就是AtomicIntegerFieldUpdater。