1. 程式人生 > >Java並發包:AtomicBoolean和AtomicReference

Java並發包:AtomicBoolean和AtomicReference

默認值 返回 java泛型 attr 一次 div 試圖 all 獲得

AtomicBoolean

AtomicBoolean是一個讀和寫都是原子性的boolean類型的變量。這裏包含高級的原子操作,例如compareAndSet()。AtomicBoolean位於Java.util.concurrent.atomic包中,因此全類名是java.util.concurrent.atomic.AtomicBoolean。這篇文章講述的AtomicBoolean的版本可以在java 8中找到,第一個版本在java 5中增加。

AtomicBoolean設計背後的原理在我的另一篇文章Compare and Swap有解釋。

創建AtomicBoolean

你可以像下面一樣創建一個AtomicBoolean:

AtomicBoolean atomicBoolean = new AtomicBoolean();
  • 1

這個例子創建了一個AtomicBoolean默認值為false。

如果你需要顯示的設置AtomicBoolean的初始值,你可以給AtomicBoolean傳遞一個初始值。

AtomicBoolean atomicBoolean = new AtomicBoolean(true);
  • 1
  • 獲取AtomicBoolean的值

你可以使用get()方法獲取AtomicBoolean的值,下面是一個例子:

AtomicBoolean atomicBoolean = new AtomicBoolean(true);

boolean value = atomicBoolean.get();
  • 1
  • 2
  • 3

執行上面的代碼後value變量的值將為ture。

  • 設置AtomicBoolean的值

你可以使用set()方法設置AtomicBoolean的值,下面是一個例子:

AtomicBoolean atomicBoolean = new AtomicBoolean(true);

atomicBoolean.set(false);
  • 1
  • 2
  • 3

執行上面的代碼後atomicBoolean 變量的值將為false。

  • 交換AtomicBoolean的值。

你可以使用getAndSet()交換AtomicBoolean的值。getAndSet()方法返回AtomicBoolean當前的值,並給它設置一個新的值。下面是一個例子:

AtomicBoolean atomicBoolean = new AtomicBoolean(true);

boolean oldValue = atomicBoolean.getAndSet(false);
  • 1
  • 2
  • 3

執行上面的代碼後oldValue的值為true,AtomicBoolean實例的值為false.代碼有效的交換了當前值為true的AtomicBoolean值使之為false。

  • 比較和設置AtomicBoolean的值

compareAndSet()可以使AtomicBoolean的當前值和你期望的值作對比。如果當前值就是你期望的值,一個新的值會在AtomicBoolean上設置。compareAndSet()方法是原子的,因此,同一時刻僅允許一個線程執行它。於是,compareAndSet()方法可以用於實現簡單的同步器例如鎖。

下面是使用compareAndSet()的例子:

AtomicBoolean atomicBoolean = new AtomicBoolean(true);

boolean expectedValue = true;
boolean newValue      = false;

boolean wasNewValueSet = atomicBoolean.compareAndSet(
    expectedValue, newValue);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

這個例子中把AtomicBoolean的當前值和true做對比,如果兩個值相等,將會給AtomicBoolean設置一個新值false。

AtomicReference

AtomicReference類提供了一種讀和寫都是原子性的對象引用變量。原子意味著多個線程試圖改變同一個AtomicReference(例如比較和交換操作)將不會使得AtomicReference處於不一致的狀態。AtomicReferenc的compareAndSet()方法可以使得它與期望的一個值進行比較,如果他們是相等的,AtomicReference裏的對象會被設置成一個新的引用。

創建AtomicReference

你可以下面這樣創建一個AtomicReference的實例。

AtomicReference atomicReference = new AtomicReference();
  • 1

如果你需要使用一個初始引用來創建AtomicReference,你可以像下面這樣做。

String initialReference = "the initially referenced string";
AtomicReference atomicReference = new AtomicReference(initialReference);
  • 1
  • 2
  • 創建泛型AtomicReference

你可以使用java泛型創建一個類型化的AtomicReference。下面是一個例子:

AtomicReference<String> atomicStringReference =
    new AtomicReference<String>();
  • 1
  • 2

你也可以給類型化的AtomicReference指定初始值,下面是給類型化的AtomicReference指定初始值的例子:

String initialReference = "the initially referenced string";
AtomicReference<String> atomicStringReference =
    new AtomicReference<String>(initialReference);
  • 1
  • 2
  • 3

獲得AtomicReference引用

你可以使用AtomicReference的get()方法獲的存儲在AtomicReference中的引用。如果你在非泛型化的AtomicReference上使用get()方法將會返回一個Object引用。如果在泛型化的AtomicReference上使用get()方法將會返回你在AtomicReference上聲明的類型的引用。

下面是一個非泛型化的AtomicReference的get()的例子:

AtomicReference atomicReference = new AtomicReference("first value referenced");

String reference = (String) atomicReference.get();
  • 1
  • 2
  • 3

註意,當AtomicReference是一個非泛型化的時,必須將get()方法返回的引用強制轉換為String,因為get()放好的是一個Object引用。

下面是一個泛型化的AtomicReference的例子:

AtomicReference<String> atomicReference = 
     new AtomicReference<String>("first value referenced");

String reference = atomicReference.get();
  • 1
  • 2
  • 3
  • 4

註意,這裏不需要將get()返回的引用進行強制轉換,因為編譯器知道它返回一個String引用。

設置AtomicReference引用

你可以使用set()方法設置儲存在AtomicReferenc實例中的引用。對於非泛型化的AtomicReference的實例,set()方法會將一個Object引用作為參數。對於泛型化的AtomicReference,set()方法將使用你在AtmoicReference上聲明的類型的引用作為參數。

下面是一個AtomicReference的set()的例子:

AtomicReference atomicReference = 
     new AtomicReference();

atomicReference.set("New object referenced");
  • 1
  • 2
  • 3
  • 4

對於泛型和非泛型的引用在使用set()上看起並沒有什麽不同。唯一的不同是編譯器會對泛型的AtomicReference有類型約束。

比較和設置AtomicReference引用

AtomicReference有一個非常有用的方法是compareAndSet()。compareAndSet()方法可以將存儲在AtomicReference中的引用同你的預期值做一個比較,如果他們是相同的(not equal as in equals() but same as in ==),那麽在AtomicReference實例上會設置一個新的引用。

如果compareAndSet()方法給AtomicReference設置了新的引用,它會返回true。否則會返回false。

下面是AtomicReference compareAndSet()方法的例子:

String initialReference = "initial value referenced";

AtomicReference<String> atomicStringReference =
    new AtomicReference<String>(initialReference);

String newReference = "new value referenced";
boolean exchanged = atomicStringReference.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);

exchanged = atomicStringReference.compareAndSet(initialReference, newReference);
System.out.println("exchanged: " + exchanged);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

上面的例子中使用了一個初始的引用創建了一個泛型化的AtomicReference。然後調用兩次compareAndSet()方法來比較儲存的引用和初始的引用。如果儲存的引用與初始引用是相等的將會設置一個新的引用。第一次的時候兩個引用是相等的,因此AtomicReference被設置了一個新的引用。第二次儲存的引用是之前調用compareAndSet()放新設置的引用,因此儲存的引用一定是與初始的引用是不相等的。於是,AtomicReference不會被設置成一個新的引用,compareAndSet()方法返回false。

Java並發包:AtomicBoolean和AtomicReference