在多線程併發請求中,我們假設有這樣的一些情景:
if(a){
xxxxx;
a = false;
yyyyy;
}
這裏存在線程安全的問題:多個線程可能都讀到a的值進入了代碼塊,然後都去修改了a的值;其實只需要一個線程執行就可以了,也就是:如何保證只初始化一次,不會重複初始化?
答案:使用AtomicBoolean類
AtomicBoolean
位於Java.util.concurrent.atomic包,這個包裏面提供了一組原子類。
基本特性:當有多個線程同時執行這些類的實例包含的方法時,具有排他性。即當某個線程進入方法,執行其中的指令時,不會被其他線程打斷,而別的線程就像自旋鎖一樣,一直等到該方法執行完成,才由JVM從等待隊列中選擇一個另一個線程進入,這只是一種邏輯上的理解。實際上是藉助硬件的相關指令來實現的,不會阻塞線程(或者說只是在硬件級別上阻塞了)。
API
1、public final boolean compareAndSet(boolean expect, boolean update); 1)當前值與expect相比較,如果相等,執行第2步,如果不相等直接返回false 2)把當前值更新爲update,並返回爲true 2、public final void set(boolean newValue); 無條件地設置爲給定值 3、public final boolean getAndSet(boolean newValue); 獲取並返回舊的值(當前值),同時,重新設置新的值。
常見用法:
public class InitXxxService{
private AtomicBoolean initState = new AtomicBoolean(false); // 注意:系統默認值也是false
@Override
public void init() {
if (! initState.compareAndSet(false, true)) {//init once
return ;
}
//TODO 寫初始化代碼
}
}
AtomicBoolean started = new AtomicBoolean(false);
if (started.compareAndSet(false, true)) {
call.enqueue(object : Callback<R> {
@override
onResponse(call: Call<R>, response: Response<R>) {
}
@override
onFailure(call: Call<R>, throwable: Throwable) {
}
});
}