jdk8 java.util包整體學習(二)concurrent.atomic包下的類

前言

java.util.concurrent.atomic 包下共有 17個類。統計代碼如下

    public static void main(String[] args) throws IOException {
        JarFile jarFile = new JarFile("/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar");
        Enumeration<JarEntry> jarEntries = jarFile.entries();
        AtomicInteger num = new AtomicInteger();
        String packageStr = "java/util/concurrent/atomic";
        jarFile.stream().forEach(m->{
            if(m.getName().startsWith(packageStr) && !m.getName().contains("$") && m.getName().endsWith("class")){
                System.out.println(m.getName().substring(m.getName().indexOf(packageStr)+packageStr.length()+1));
                num.getAndIncrement();
            }
        });
        System.out.println("共有類:"+num.toString());
    

結果如下:
在這裏插入圖片描述

包簡介

atmic 包主要支持單變量上的無鎖線程安全編程。
分類:

  • 原子更新基本類型類
    • AtomicBoolean:原子更新布爾類型。
    • AtomicInteger:原子更新整型。
    • AtomicLong:原子更新長整型。
  • 原子更新數組類
    • AtomicIntegerArray:原子更新整型數組裏的元素。
    • AtomicLongArray:原子更新長整型數組裏的元素。
    • AtomicReferenceArray:原子更新引用類型數組裏的元素。
  • 原子更新引用類型
    • AtomicReference:原子更新引用類型。
    • AtomicReferenceFieldUpdater:原子更新引用類型裏的字段。
    • AtomicIntegerFieldUpdater:原子更新整型的字段的更新器。
    • AtomicLongFieldUpdater:原子更新長整型字段的更新器。
    • AtomicStampedReference:原子更新帶有版本號的引用類型。該類將整數值與引用關聯起來,可用於原子的更數據和數據的版本號,可以解決使用CAS進行原子更新時,可能出現的ABA問題。
  • 針對 Atomic 相關數字類的改進類
    • LongAdder
    • LongAccumulator
    • DoubleAdder
    • DoubleAccumulator

原子更新基本類型

AtomicBoolean

常用方法:

  • public final boolean compareAndSet(boolean expect,
    boolean update)
    如果當前值 == 預期值,則以原子方式將該值設置爲給定的更新值。
    參數:
    expect - 預期值
    update - 新值
    返回:
    如果成功,則返回 true。返回 False 指示實際值與預期值不相等。
  • getAndSet
    public final boolean getAndSet(boolean newValue)
    以原子方式設置爲給定值,並返回以前的值。
    參數:
    newValue - 新值
    返回:
    以前的值

AtomicInteger

常用方法(如果涉及加減,則只列舉加):

  • incrementAndGet 自增,返回最新的值
  • addAndGet 做加法,並返回最新的值
  • compareAndSet 設置值,並返回是否設置成功

AtomicLong

常用方法(如果涉及加減,則只列舉加):

  • incrementAndGet 自增,返回最新的值
  • addAndGet 做加法,並返回最新的值
  • compareAndSet 設置值,並返回是否設置成功

原子更新數組類

注意:

  • 原子更新數組類不會直接操作傳入的數組,而是操作自己 clone 的傳入的數組的副本

AtomicIntegerArray

常用方法:

  • addAndGet(int i, int delta) cas 更新下標爲 i 的數字爲 當前數+delta,並返回最新值
  • incrementAndGet(int i) cas 下標爲 i 的元素進行自增,並返回最新值
  • compareAndSet(int i, int expect, int update) 比較下標爲 i 的元素和 expect,相等則更新爲 update,返回是否更新成功

AtomicLongArray

類似 AtomicIntegerArray

AtomicReferenceArray

常用方法:

  • compareAndSet(int i, E expect, E update) 比較下標爲 i 的引用和 expect 是否相同,相同的話,則將引用更新爲 update。返回值爲是否更新

原子更新引用類型

AtomicReference

原子更新引用

AtomicReferenceFieldUpdater

原子更新引用對象字段。這個類是基於反射的一個工具類。被更新的字段需要滿足以下要求:

  • 被 volatile 修飾(保證可見行)
  • 不能被 private 修飾符修飾

核心方法:

  • AtomicReferenceFieldUpdater<U,W> newUpdater(Class< U> tclass,
    Class< W> vclass,
    String fieldName) 生成一個更新器。
  • compareAndSet(T obj, V expect, V update) 比較並跟新 obj 的字段值,並返回是否成功更新

使用示例:

    @org.junit.Test
    public void testAtomicReferenceFieldUpdater(){
        Person person = new Person("小田切讓",20);
        AtomicReferenceFieldUpdater fieldUpdater = AtomicReferenceFieldUpdater.newUpdater(Person.class,Integer.class,"age");
        fieldUpdater.compareAndSet(person,person.getAge(),new Integer(33));
        System.out.println(person.getAge());
    }
@AllArgsConstructor
@Data
class Person{
    private String name;

    public volatile Integer age;
}

AtomicIntegerFieldUpdater

修改引用對象中被 int 修飾的字段。該字段必須滿足以下要求:

  • 被 int 修飾,不能使用包裝類型 Integer 修飾
  • 必須被 volatile 修飾
  • 不能被 private 修飾

常用方法:

  • newUpdater(Class tclass,String fieldName) 生成字段更新器
  • incrementAndGet(T obj) obj 的字段自增,並返回最新值
  • compareAndSet(T obj, int expect, int update)

示例:

    @org.junit.Test
    public void testAtomicIntegerFieldUpdater(){
        Person person = new Person("小田切讓",new Integer(20));
        AtomicIntegerFieldUpdater<Person> updater  = AtomicIntegerFieldUpdater.newUpdater(Person.class,"age");
        updater.incrementAndGet(person);
        updater.compareAndSet(person,person.getAge(),new Integer(25));
        System.out.println(person.getAge());
    }

@AllArgsConstructor
@Data
class Person{
    private String name;

    public volatile int age;
}

AtomicLongFieldUpdater

類似 AtomicIntegerFieldUpdater ,修改引用對象中被 long 修飾的字段。該字段必須滿足以下要求:

  • 被 long 修飾,不能使用包裝類型 Long 修飾
  • 必須被 volatile 修飾
  • 不能被 private 修飾

AtomicStampedReference

解決原子更新引用的「ABA」問題

常用方法:

  • compareAndSet(V expectedReference,
    V newReference,
    int expectedStamp,
    int newStamp) 比較引用和標誌,都相同才進行更新,並返回更新結果

示例:

    @org.junit.Test
    public void testAtomicStampedReference(){
        Person person = new Person("小田切讓",20);
        AtomicStampedReference<Person> reference = new AtomicStampedReference<>(person,100);
        reference.compareAndSet(person,new Person("小栗旬",23),100,101);
        System.out.println(reference.getReference().getName());
        System.out.println(reference.getStamp());
    }

針對 Atomic 相關數字類的改進類

LongAdder

針對 AtomicLong 的改進類,在高併發的情況下,擁有更好的表現
常用方法:

  • add(long x) 加法
  • increment() 自增
  • decrement() 自減

DoubleAdder

常用方法:

  • add(double x)

LongAccumulator

LongAdder 只提供了「加」操作,假如需要對當前結果 m 進行 m*5+1,這種複合運算,則需要 LongAccumulator。
ongAdder類是LongAccumulator的一個特例,LongAccumulator提供了比LongAdder更強大的功能,如下構造函數,其中accumulatorFunction是一個雙目運算器接口,根據輸入的兩個參數返回一個計算值(兩個參數分別代表,當前值,輸入值),identity則是LongAccumulator累加器的初始值。
常用方法:

  • LongAccumulator(LongBinaryOperator accumulatorFunction,
    long identity)
  • accumulate(long x) 進行一次計算

demo:

    @org.junit.Test
    public void testLongAccumulator(){
        LongAccumulator longAccumulator = new LongAccumulator((m,n)-> {
            return m*n+1; // 這裏結果其實是 100 * 10 +1
        },100);
        longAccumulator.accumulate(10);
        System.out.println(longAccumulator.longValue());
    }

DoubleAccumulator

類似 LongAccumulator

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章