1. 程式人生 > >cocurrent包 原子性數據類型

cocurrent包 原子性數據類型

gre 兩種方法 實例 oar start 如果 個數 tutorial 操作

22. 原子性布爾 AtomicBoolean

AtomicBoolean 類為我們提供了一個可以用原子方式進行讀和寫的布爾值,它還擁有一些先進的原子性操作,比如 compareAndSet()。AtomicBoolean 類位於 java.util.concurrent.atomic 包,完整類名是為 java.util.concurrent.atomic.AtomicBoolean。本小節描述的 AtomicBoolean 是 Java 8 版本裏的,而不是它第一次被引入的 Java 5 版本。
AtomicBoolean 背後的設計理念在我的《Java 並發指南》主題的《比較和交換》小節有解釋。

創建一個 AtomicBoolean

你可以這樣創建一個 AtomicBoolean:

[java] view plain copy
  1. AtomicBoolean atomicBoolean = new AtomicBoolean();


以上示例新建了一個默認值為 false 的 AtomicBoolean。
如果你想要為 AtomicBoolean 實例設置一個顯式的初始值,那麽你可以將初始值傳給 AtomicBoolean 的構造子:

[java] view plain copy
  1. AtomicBoolean atomicBoolean = new AtomicBoolean(true);

獲取 AtomicBoolean 的值

你可以通過使用 get() 方法來獲取一個 AtomicBoolean 的值。示例如下:

[java] view plain copy
  1. AtomicBoolean atomicBoolean = new AtomicBoolean(true);
  2. boolean value = atomicBoolean.get();


以上代碼執行後 value 變量的值將為 true。

設置 AtomicBoolean 的值

你可以通過使用 set() 方法來設置一個 AtomicBoolean 的值。示例如下:

[java] view plain copy
  1. AtomicBoolean atomicBoolean = new AtomicBoolean(true);
  2. atomicBoolean.set(false);


以上代碼執行後 AtomicBoolean 的值為 false。

交換 AtomicBoolean 的值

你可以通過 getAndSet() 方法來交換一個 AtomicBoolean 實例的值。getAndSet() 方法將返回 AtomicBoolean 當前的值,並將為 AtomicBoolean 設置一個新值。示例如下:

[java] view plain copy
  1. AtomicBoolean atomicBoolean = new AtomicBoolean(true);
  2. boolean oldValue = atomicBoolean.getAndSet(false);


以上代碼執行後 oldValue 變量的值為 true,atomicBoolean 實例將持有 false 值。代碼成功將 AtomicBoolean 當前值 ture 交換為 false。

比較並設置 AtomicBoolean 的值

compareAndSet() 方法允許你對 AtomicBoolean 的當前值與一個期望值進行比較,如果當前值等於期望值的話,將會對 AtomicBoolean 設定一個新值。compareAndSet() 方法是原子性的,因此在同一時間之內有單個線程執行它。因此 compareAndSet() 方法可被用於一些類似於鎖的同步的簡單實現。
以下是一個 compareAndSet() 示例:

[java] view plain copy
  1. AtomicBoolean atomicBoolean = new AtomicBoolean(true);
  2. boolean expectedValue = true;
  3. boolean newValue = false;
  4. boolean wasNewValueSet = atomicBoolean.compareAndSet(
  5. expectedValue, newValue);

本示例對 AtomicBoolean 的當前值與 true 值進行比較,如果相等,將 AtomicBoolean 的值更新為 false。

23. 原子性整型 AtomicInteger

AtomicInteger 類為我們提供了一個可以進行原子性讀和寫操作的 int 變量,它還包含一系列先進的原子性操作,比如 compareAndSet()。AtomicInteger 類位於 java.util.concurrent.atomic 包,因此其完整類名為 java.util.concurrent.atomic.AtomicInteger。本小節描述的 AtomicInteger 是 Java 8 版本裏的,而不是它第一次被引入的 Java 5 版本。
AtomicInteger 背後的設計理念在我的《Java 並發指南》主題的《比較和交換》小節有解釋。

創建一個 AtomicInteger

創建一個 AtomicInteger 示例如下:

[java] view plain copy
  1. AtomicInteger atomicInteger = new AtomicInteger();


本示例將創建一個初始值為 0 的 AtomicInteger。
如果你想要創建一個給定初始值的 AtomicInteger,你可以這樣:

[java] view plain copy
  1. AtomicInteger atomicInteger = new AtomicInteger(123);


本示例將 123 作為參數傳給 AtomicInteger 的構造子,它將設置 AtomicInteger 實例的初始值為 123。

獲取 AtomicInteger 的值

你可以使用 get() 方法獲取 AtomicInteger 實例的值。示例如下:

[java] view plain copy
  1. AtomicInteger atomicInteger = new AtomicInteger(123);
  2. int theValue = atomicInteger.get();

設置 AtomicInteger 的值

你可以通過 set() 方法對 AtomicInteger 的值進行重新設置。以下是 AtomicInteger.set() 示例:

[java] view plain copy
  1. AtomicInteger atomicInteger = new AtomicInteger(123);
  2. atomicInteger.set(234);


以上示例創建了一個初始值為 123 的 AtomicInteger,而在第二行將其值更新為 234。

比較並設置 AtomicInteger 的值

AtomicInteger 類也通過了一個原子性的 compareAndSet() 方法。這一方法將 AtomicInteger 實例的當前值與期望值進行比較,如果二者相等,為 AtomicInteger 實例設置一個新值。AtomicInteger.compareAndSet() 代碼示例:

[java] view plain copy
  1. AtomicInteger atomicInteger = new AtomicInteger(123);
  2. int expectedValue = 123;
  3. int newValue = 234;
  4. atomicInteger.compareAndSet(expectedValue, newValue);


本示例首先新建一個初始值為 123 的 AtomicInteger 實例。然後將 AtomicInteger 與期望值 123 進行比較,如果相等,將 AtomicInteger 的值更新為 234。

增加 AtomicInteger 值

AtomicInteger 類包含有一些方法,通過它們你可以增加 AtomicInteger 的值,並獲取其值。這些方法如下:

  • addAndGet()
  • getAndAdd()
  • getAndIncrement()
  • incrementAndGet()

第一個 addAndGet() 方法給 AtomicInteger 增加了一個值,然後返回增加後的值。getAndAdd() 方法為 AtomicInteger 增加了一個值,但返回的是增加以前的 AtomicInteger 的值。具體使用哪一個取決於你的應用場景。以下是這兩種方法的示例:

[java] view plain copy
  1. AtomicInteger atomicInteger = new AtomicInteger();
  2. System.out.println(atomicInteger.getAndAdd(10));
  3. System.out.println(atomicInteger.addAndGet(10));


本示例將打印出 0 和 20。例子中,第二行拿到的是加 10 之前的 AtomicInteger 的值。加 10 之前的值是 0。第三行將 AtomicInteger 的值再加 10,並返回加操作之後的值。該值現在是為 20。
你當然也可以使用這倆方法為 AtomicInteger 添加負值。結果實際是一個減法操作。
getAndIncrement() 和 incrementAndGet() 方法類似於 getAndAdd() 和 addAndGet(),但每次只將 AtomicInteger 的值加 1。

減小 AtomicInteger 的值

AtomicInteger 類還提供了一些減小 AtomicInteger 的值的原子性方法。這些方法是:

  • decrementAndGet()
  • getAndDecrement()

decrementAndGet() 將 AtomicInteger 的值減一,並返回減一後的值。getAndDecrement() 也將 AtomicInteger 的值減一,但它返回的是減一之前的值。

24. 原子性長整型 AtomicLong

AtomicLong 類為我們提供了一個可以進行原子性讀和寫操作的 long 變量,它還包含一系列先進的原子性操作,比如 compareAndSet()AtomicLong 類位於 java.util.concurrent.atomic 包,因此其完整類名為 java.util.concurrent.atomic.AtomicLong。本小節描述的 AtomicLong 是 Java 8 版本裏的,而不是它第一次被引入的 Java 5 版本。
AtomicLong 背後的設計理念在我的《Java 並發指南》主題的《比較和交換》小節有解釋。

創建一個 AtomicLong

創建一個 AtomicLong 如下:

[java] view plain copy
  1. AtomicLong atomicLong = new AtomicLong();


將創建一個初始值為 0 的 AtomicLong。
如果你想創建一個指定初始值的 AtomicLong,可以:

[java] view plain copy
  1. AtomicLong atomicLong = new AtomicLong(123);


本示例將 123 作為參數傳遞給 AtomicLong 的構造子,後者將 AtomicLong 實例的初始值設置為 123。

獲取 AtomicLong 的值

你可以通過 get() 方法獲取 AtomicLong 的值。AtomicLong.get() 示例:

[java] view plain copy
  1. AtomicLong atomicLong = new AtomicLong(123);
  2. long theValue = atomicLong.get();

設置 AtomicLong 的值

你可以通過 set() 方法設置 AtomicLong 實例的值。一個 AtomicLong.set() 的示例:

[java] view plain copy
  1. AtomicLong atomicLong = new AtomicLong(123);
  2. atomicLong.set(234);


本示例新建了一個初始值為 123 的 AtomicLong,第二行將其值設置為 234。

比較並設置 AtomicLong 的值

AtomicLong 類也有一個原子性的 compareAndSet() 方法。這一方法將 AtomicLong 實例的當前值與一個期望值進行比較,如果兩種相等,為 AtomicLong 實例設置一個新值。AtomicLong.compareAndSet() 使用示例:

[java] view plain copy
  1. AtomicLong atomicLong = new AtomicLong(123);
  2. long expectedValue = 123;
  3. long newValue = 234;
  4. atomicLong.compareAndSet(expectedValue, newValue);

本示例新建了一個初始值為 123 的 AtomicLong。然後將 AtomicLong 的當前值與期望值 123 進行比較,如果相等的話,AtomicLong 的新值將變為 234。

增加 AtomicLong 值

AtomicLong 具備一些能夠增加 AtomicLong 的值並返回自身值的方法。這些方法如下:

  • addAndGet()
  • getAndAdd()
  • getAndIncrement()
  • incrementAndGet()

第一個方法 addAndGet() 將 AtomicLong 的值加一個數字,並返回增加後的值。第二個方法 getAndAdd() 也將 AtomicLong 的值加一個數字,但返回的是增加前的 AtomicLong 的值。具體使用哪一個取決於你自己的場景。示例如下:

[java] view plain copy
  1. AtomicLong atomicLong = new AtomicLong();
  2. System.out.println(atomicLong.getAndAdd(10));
  3. System.out.println(atomicLong.addAndGet(10));


本示例將打印出 0 和 20。例子中,第二行拿到的是加 10 之前的 AtomicLong 的值。加 10 之前的值是 0。第三行將 AtomicLong 的值再加 10,並返回加操作之後的值。該值現在是為 20。
你當然也可以使用這倆方法為 AtomicLong 添加負值。結果實際是一個減法操作。
getAndIncrement() 和 incrementAndGet() 方法類似於 getAndAdd() 和 addAndGet(),但每次只將 AtomicLong 的值加 1。

減小 AtomicLong 的值

AtomicLong 類還提供了一些減小 AtomicLong 的值的原子性方法。這些方法是:

  • decrementAndGet()
  • getAndDecrement()

decrementAndGet() 將 AtomicLong 的值減一,並返回減一後的值。getAndDecrement() 也將 AtomicLong 的值減一,但它返回的是減一之前的值。

25. 原子性引用型 AtomicReference

AtomicReference 提供了一個可以被原子性讀和寫的對象引用變量。原子性的意思是多個想要改變同一個 AtomicReference 的線程不會導致 AtomicReference 處於不一致的狀態。AtomicReference 還有一個 compareAndSet() 方法,通過它你可以將當前引用於一個期望值(引用)進行比較,如果相等,在該 AtomicReference 對象內部設置一個新的引用。

創建一個 AtomicReference

創建 AtomicReference 如下:

[java] view plain copy
  1. AtomicReference atomicReference = new AtomicReference();


如果你需要使用一個指定引用創建 AtomicReference,可以:

[java] view plain copy
  1. String initialReference = "the initially referenced string";
  2. AtomicReference atomicReference = new AtomicReference(initialReference);

創建泛型 AtomicReference

你可以使用 Java 泛型來創建一個泛型 AtomicReference。示例:

[java] view plain copy
  1. AtomicReference<String> atomicStringReference =
  2. new AtomicReference<String>();


你也可以為泛型 AtomicReference 設置一個初始值。示例:

[java] view plain copy
  1. String initialReference = "the initially referenced string";
  2. AtomicReference<String> atomicStringReference =
  3. new AtomicReference<String>(initialReference);

獲取 AtomicReference 引用

你可以通過 AtomicReference 的 get() 方法來獲取保存在 AtomicReference 裏的引用。如果你的 AtomicReference 是非泛型的,get() 方法將返回一個 Object 類型的引用。如果是泛型化的,get() 將返回你創建 AtomicReference 時聲明的那個類型。
先來看一個非泛型的 AtomicReference get() 示例:

[java] view plain copy
  1. AtomicReference atomicReference = new AtomicReference("first value referenced");
  2. String reference = (String) atomicReference.get();


註意如何對 get() 方法返回的引用強制轉換為 String。
泛型化的 AtomicReference 示例:

[java] view plain copy
  1. AtomicReference<String> atomicReference =
  2. new AtomicReference<String>("first value referenced");
  3. String reference = atomicReference.get();


編譯器知道了引用的類型,所以我們無需再對 get() 返回的引用進行強制轉換了。

設置 AtomicReference 引用

你可以使用 get() 方法對 AtomicReference 裏邊保存的引用進行設置。如果你定義的是一個非泛型 AtomicReference,set() 將會以一個 Object 引用作為參數。如果是泛型化的 AtomicReference,set() 方法將只接受你定義給的類型。
AtomicReference set() 示例:

[java] view plain copy
  1. AtomicReference atomicReference =
  2. new AtomicReference();
  3. atomicReference.set("New object referenced");


這個看起來非泛型和泛型化的沒啥區別。真正的區別在於編譯器將對你能夠設置給一個泛型化的 AtomicReference 參數類型進行限制。

比較並設置 AtomicReference 引用

AtomicReference 類具備了一個很有用的方法:compareAndSet()。compareAndSet() 可以將保存在 AtomicReference 裏的引用於一個期望引用進行比較,如果兩個引用是一樣的(並非 equals() 的相等,而是 == 的一樣),將會給 AtomicReference 實例設置一個新的引用。
如果 compareAndSet() 為 AtomicReference 設置了一個新的引用,compareAndSet() 將返回 true。否則 compareAndSet() 返回 false。
AtomicReference compareAndSet() 示例:

[java] view plain copy
  1. String initialReference = "initial value referenced";
  2. AtomicReference<String> atomicStringReference =
  3. new AtomicReference<String>(initialReference);
  4. String newReference = "new value referenced";
  5. boolean exchanged = atomicStringReference.compareAndSet(initialReference, newReference);
  6. System.out.println("exchanged: " + exchanged);
  7. exchanged = atomicStringReference.compareAndSet(initialReference, newReference);
  8. System.out.println("exchanged: " + exchanged);


本示例創建了一個帶有一個初始引用的泛型化的 AtomicReference。之後兩次調用 comparesAndSet()來對存儲值和期望值進行對比,如果二者一致,為 AtomicReference 設置一個新的引用。第一次比較,存儲的引用(initialReference)和期望的引用(initialReference)一致,所以一個新的引用(newReference)被設置給 AtomicReference,compareAndSet() 方法返回 true。第二次比較時,存儲的引用(newReference)和期望的引用(initialReference)不一致,因此新的引用沒有被設置給 AtomicReference,compareAndSet() 方法返回 false。

cocurrent包 原子性數據類型