最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java的Atomic原子類詳解

 更新時(shí)間:2023年09月25日 12:25:54   作者:2201_75761617  
這篇文章主要介紹了Java的Atomic原子類詳解,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

Java SDK 并發(fā)包里提供了豐富的原子類,我們可以將其分為五個(gè)類別,這五個(gè)類別提供的方法基本上是相似的,并且每個(gè)類別都有若干原子類。

  • 對基本數(shù)據(jù)類型的變量值進(jìn)行原子更新;
  • 對對象變量的指向進(jìn)行原子更新;
  • 對數(shù)組里面的的元素進(jìn)行原子更新;
  • 原子化的對象屬性更新器;
  • 原子化的累加器。

007a32583fbf519469462fe61805eb4a.png

基本數(shù)據(jù)類型

AtomicBoolean、AtomicLong、AtomicInteger 這三個(gè)類提供了一些對基本數(shù)據(jù)類型的變量值進(jìn)行原子更新的方法。

這些類提供的方法是相似的,主要有(以 AtomicLong 為例):

// 原子化的 i++
long getAndIncrement()
// 原子化的 i--
long getAndDecrement()
// 原子化的 ++i
long incrementAndGet()
// 原子化的 --i
long decrementAndGet()
// 原子化的 i+=delta,返回值為+=前的i值
long getAndAdd(long delta)
// 原子化的 i+=delta,返回值為+=后的i值
long addAndGet(delta)
// CAS操作。如果寫回成功返回true,否則返回false
boolean compareAndSet(long expect, long update)
// 以下四個(gè)方法新值可以通過傳入函數(shù)式接口(func函數(shù))來計(jì)算
long getAndUpdate(LongUnaryOperator updateFunction)
long updateAndGet(LongUnaryOperator updateFunction)
long getAndAccumulate(long x, LongBinaryOperator accumulatorFunction)
long accumulateAndGet(long x, LongBinaryOperator accumulatorFunction)
// 演示 getAndUpdate() 方法的使用
public static void main(String[] args) {
    AtomicLong atomicLong = new AtomicLong(0);
    long result = atomicLong.getAndUpdate(new LongUnaryOperator() {
        @Override
        public long applyAsLong(long operand) {
            return operand + 1;
        }
    });
}

對象引用類型

AtomicReference、AtomicStampedReference、AtomicMarkableReference 這三個(gè)類提供了一些對對象變量的指向進(jìn)行原子更新的方法。如果需要對對象的屬性進(jìn)行原子更像,那么可以使用原子化的對象屬性更新器。

public class ClassName {
    AtomicReference<Employee> employeeAR = new AtomicReference<>(new Employee("小明"));
    public void methodName() {
        Employee oldVal = employeeAR.get();
        Employee newVal = new Employee(oldVal.getName());
        employeeAR.compareAndSet(oldVal, newVal);
    }
}

對象引用的原子化更新需要重點(diǎn)關(guān)注 ABA 問題。當(dāng)一個(gè)線程在進(jìn)行 CAS 操作時(shí),另一個(gè)線程可能會在此期間修改了同一個(gè)共享變量的值,然后又將其改回原來的值。這種情況下,CAS 操作就無法檢測到共享變量值的變化,從而導(dǎo)致 ABA 問題。如果我們僅僅在寫回?cái)?shù)據(jù)前判斷數(shù)值是 A,可能導(dǎo)致不合理的寫回操作。AtomicStampedReference 和 AtomicMarkableReference 這兩個(gè)原子類可以解決 ABA 問題。

  • AtomicStampedReference 通過為對象引用建立類似版本號(stamp)的方式,來解決 ABA 問題。
  • AtomicStampedReference 實(shí)現(xiàn)的 CAS 方法增加了版本號參數(shù)AtomicMarkableReference 的實(shí)現(xiàn)機(jī)制則更簡單,將版本號簡化成了一個(gè) Boolean 值
boolean compareAndSet(V expectedReference, V newReference, 
                          int expectedStamp, int newStamp)
boolean compareAndSet(V expectedReference, V newReference,
                          boolean expectedMark, boolean newMark)

數(shù)組

AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray 這三個(gè)類提供了一些對數(shù)組里面的的元素進(jìn)行原子更新的方法。

public class ClassName {
    AtomicLongArray atomicLongArray = new AtomicLongArray(new long[]{0, 1});
    public void methodName() {
        int index = 0;
        long oldVal = atomicLongArray.get(index);
        long newVal = oldVal + 1;
        atomicLongArray.compareAndSet(index, oldVal, newVal);
    }
}

原子化的對象屬性更新器

原子化的對象屬性更新器有:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater。

這三個(gè)類提供了一些對對象的屬性進(jìn)行原子更新的方法。這些方法是利用反射機(jī)制實(shí)現(xiàn)的。

public class ClassName {
    AtomicIntegerFieldUpdater<Employee> fieldUpdater =
            AtomicIntegerFieldUpdater.newUpdater(Employee.class, "salary");
    Employee employee = new Employee("小明", 1000);
    public void methodName() {
        int oldVal = employee.getSalary();
        int newVal = oldVal + 1000;
        fieldUpdater.compareAndSet(employee, oldVal, newVal);
    }
}

需要注意的是:

  • 對象屬性的類型必須是基本數(shù)據(jù)類型,不能是基本數(shù)據(jù)類型對應(yīng)的包裝類。如果對象屬性的類型不是基本數(shù)據(jù)類型,newUpdater() 方法會拋出 IllegalArgumentException 運(yùn)行時(shí)異常。
  • 對象的屬性必須是 volatile 類型的,只有這樣才能保證可見性。如果對象的屬性不是 volatile 類型的,newUpdater() 方法會拋出 IllegalArgumentException 運(yùn)行時(shí)異常。
// AtomicIntegerFieldUpdater 類中的代碼
if (field.getType() != int.class) {
    throw new IllegalArgumentException("Must be integer type");
}
if (!Modifier.isVolatile(modifiers)) {
    throw new IllegalArgumentException("Must be volatile type");
}

原子化的累加器

原子化的累加器有:LongAdder、DoubleAdder、LongAccumulator、DoubleAccumulator。這四個(gè)類僅僅用來在多線程環(huán)境下,執(zhí)行累加操作。

相比原子化的基本數(shù)據(jù)類型,原子化的累加器的速度更快,但是它(原子化的累加器)不支持 compareAndSet() 方法。如果僅僅需要累加操作,使用原子化的累加器性能會更好。

原子化的累加器的本質(zhì)是空間換時(shí)間。

LongAdder 的使用示例如下所示:

public static void main(String[] args) {
    LongAdder adder = new LongAdder();
    // 初始化
    adder.add(1);
    // 累加
    for (int i = 0; i < 100; i++) {
        adder.increment();
    }
    long sum = adder.sum();
}

LongAccumulator 與 LongAdder 類似,但 LongAccumulator 提供了更加靈活的累加操作,可以自定義累加函數(shù)。

使用示例如下所示。在使用示例中,我們創(chuàng)建了一個(gè) LongAccumulator 對象,初始值為1,累加函數(shù)為 (x, y) -> x * y,即每次累加都將之前的結(jié)果與新的值相乘。然后,我們累加了三個(gè)數(shù)值,最后輸出累加結(jié)果。由于累加函數(shù)是(x, y) -> x * y,所以最終的累加結(jié)果為1 * 5 * 10 * 20 = 1000。 

public static void main(String[] args) {
    LongAccumulator accumulator = new LongAccumulator(new LongBinaryOperator() {
        @Override
        public long applyAsLong(long left, long right) {
            return left * right;
        }
    }, 1);
    // 初始值為1,累加函數(shù)為(x, y) -> x * y
    accumulator.accumulate(5);
    accumulator.accumulate(10);
    accumulator.accumulate(20);
    // 累加結(jié)果為 1 * 5 * 10 * 20 = 1000
    long result = accumulator.get();
}

到此這篇關(guān)于Java的Atomic原子類的文章就介紹到這了,更多相關(guān)Java Atomic原子類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于弗洛伊德算法求最短路徑詳解

    關(guān)于弗洛伊德算法求最短路徑詳解

    這篇文章主要介紹了關(guān)于弗洛伊德算法求最短路徑詳解,弗洛伊德算法VS迪杰斯特拉算法:迪杰斯特拉算法通過選定的被訪問頂點(diǎn),求出從出發(fā)訪問頂點(diǎn)到其他項(xiàng)點(diǎn)的最短路徑:弗洛伊德算法中每-個(gè)頂點(diǎn)都是出發(fā)訪問點(diǎn),需要的朋友可以參考下
    2023-07-07
  • JDK1.6“新“特性Instrumentation之JavaAgent(推薦)

    JDK1.6“新“特性Instrumentation之JavaAgent(推薦)

    這篇文章主要介紹了JDK1.6“新“特性Instrumentation之JavaAgent,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 如何解決java:錯(cuò)誤:無效的源發(fā)行版:17問題

    如何解決java:錯(cuò)誤:無效的源發(fā)行版:17問題

    這篇文章主要介紹了如何解決java:錯(cuò)誤:無效的源發(fā)行版:17問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java實(shí)現(xiàn)HTML轉(zhuǎn)PDF及合并PDF文件詳細(xì)教程

    Java實(shí)現(xiàn)HTML轉(zhuǎn)PDF及合并PDF文件詳細(xì)教程

    之前在工作中遇到過一個(gè)需求,是將用戶填寫的申報(bào),由固定模板的來生成pdf,后來想到先把內(nèi)容生成html,然后再把html格式的內(nèi)容轉(zhuǎn)換成pdf,這篇文章主要介紹了Java實(shí)現(xiàn)HTML轉(zhuǎn)PDF及合并PDF文件的相關(guān)資料,需要的朋友可以參考下
    2025-07-07
  • Java基于UDP協(xié)議實(shí)現(xiàn)簡單的聊天室程序

    Java基于UDP協(xié)議實(shí)現(xiàn)簡單的聊天室程序

    這篇文章主要為大家詳細(xì)介紹了Java基于UDP協(xié)議實(shí)現(xiàn)簡單的聊天室程序的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • CountDownLatch和Atomic原子操作類源碼解析

    CountDownLatch和Atomic原子操作類源碼解析

    這篇文章主要為大家介紹了CountDownLatch和Atomic原子操作類的源碼解析以及理解應(yīng)用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • springboot?靜態(tài)方法中使用@Autowired注入方式

    springboot?靜態(tài)方法中使用@Autowired注入方式

    這篇文章主要介紹了springboot?靜態(tài)方法中使用@Autowired注入方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • java兩個(gè)數(shù)組合并為一個(gè)數(shù)組的幾種方法

    java兩個(gè)數(shù)組合并為一個(gè)數(shù)組的幾種方法

    這篇文章主要給大家介紹了關(guān)于java兩個(gè)數(shù)組合并為一個(gè)數(shù)組的幾種方法,最近在寫代碼時(shí)遇到了需要合并兩個(gè)數(shù)組的需求,文中將每種方法都介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • 新手易懂的Java客戶管理小項(xiàng)目

    新手易懂的Java客戶管理小項(xiàng)目

    本篇文章是作為一個(gè)很適合新手閱讀的初級小項(xiàng)目,客戶管理,它主要實(shí)現(xiàn)數(shù)據(jù)庫的增刪查改操作,管理每位客戶的不同信息,如果你也是開始學(xué)Java不久,這篇文章將很適合你
    2021-11-11
  • java線程池使用及原理面試題

    java線程池使用及原理面試題

    很多面試官喜歡把線程池作為問題的起點(diǎn),然后延伸到其它內(nèi)容,由于我們專欄已經(jīng)說過隊(duì)列、線程、鎖面試題了,所以本章面試題還是以線程池為主
    2022-03-03

最新評論

中山市| 万荣县| 六枝特区| 仙居县| 达州市| 湟中县| 宿松县| 铅山县| 黑河市| 永年县| 巴林左旗| 新建县| 铅山县| SHOW| 盐池县| 大荔县| 郴州市| 高淳县| 错那县| 开封县| 元江| 土默特左旗| 崇义县| 安庆市| 富顺县| 合作市| 虹口区| 弋阳县| 衡阳市| 托克逊县| 翁源县| 烟台市| 乐山市| 凤山县| 梁河县| 铜山县| 囊谦县| 巴中市| 霍山县| 都昌县| 吉林市|