併發編程--原子操做、阻塞隊列

J.U.C 中的阻塞隊列

在 Java8 中,提供了 7 個阻塞隊列

ArrayBlockingQueue 數組實現的有界阻塞隊列, 此隊列按照先進先出(FIFO)的原則對元素進行排序。
LinkedBlockingQueue 鏈表實現的有界阻塞隊列, 此隊列的默認和最大長度爲Integer.MAX_VALUE。此隊列按照先進先出的原則對元素進行排序
PriorityBlockingQueue 支持優先級排序的無界阻塞隊列, 默認狀況下元素採起天然順序升序排列。也能夠自定義類實現 compareTo()方法來指定元素排序規則,或者初始化 PriorityBlockingQueue 時,指定構造參數 Comparator 來對元素進行排序。
DelayQueue 優先級隊列實現的無界阻塞隊列
SynchronousQueue 不存儲元素的阻塞隊列, 每個 put 操做必須等待一個 take 操做,不然不能繼續添加元素。
LinkedTransferQueue 鏈表實現的無界阻塞隊列
LinkedBlockingDeque 鏈表實現的雙向阻塞隊列

阻塞隊列的操做方法

在阻塞隊列中,提供了四種處理方式數組

  1. 插入操做
    add(e) :添加元素到隊列中,若是隊列滿了,繼續插入元素會報錯,IllegalStateException。 offer(e) : 添加元素到隊列,同時會返回元素是否插入成功的狀態,若是成功則返回 true put(e) :當阻塞隊列滿了之後,生產者繼續經過 put添加元素,隊列會一直阻塞生產者線程,知道隊列可用 offer(e,time,unit) :當阻塞隊列滿了之後繼續添加元素,生產者線程會被阻塞指定時間,若是超時,則線程直接退出
  2. 移除操做 remove():當隊列爲空時,調用 remove 會返回 false,若是元素移除成功,則返回 true poll(): 當隊列中存在元素,則從隊列中取出一個元素,若是隊列爲空,則直接返回 null take():基於阻塞的方式獲取隊列中的元素,若是隊列爲空,則 take 方法會一直阻塞,直到隊列中有新的數據,put 操做將會喚醒 take 線程能夠消費 poll(time,unit):帶超時機制的獲取數據,若是隊列爲空,則會等待指定的時間再去獲取元素返回

J.U.C 中的原子操做類

因爲變量類型的關係,在 J.U.C 中提供了 12 個原子操做的類。這 12 個類能夠分爲四大類多線程

  1. 原子更新基本類型
    AtomicBoolean、AtomicInteger、AtomicLong
  2. 原子更新數組
    AtomicIntegerArray 、 AtomicLongArray 、AtomicReferenceArray
  3. 原子更新引用 AtomicReference 、 AtomicReferenceFieldUpdater 、AtomicMarkableReference(更新帶有標記位的引用類型)
  4. 原子更新字段 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicStampedReferenceAtomicInteger 原理分析
AtomicInteger

getAndIncrement
getAndIncrement 其實是調用 unsafe 這個類裏面提供的方法,Unsafe 類咱們前面在分析 AQS 的時候講過,這個類至關因而一個後門,使得 Java 能夠像 C 語言的指針同樣直接操做內存空間。固然也會帶來一些弊端,就是指針的問題。實際上這個類在不少方面都有使用,除了 J.U.C 這個包之外,還有 Netty、kafka 等等這個類提供了不少功能,包括多線程同步(monitorEnter)、CAS 操 做 (compareAndSwap) 、線程的掛起和恢復(park/unpark)、內存屏障(loadFence/storeFence)內存管理(內存分配、釋放內存、獲取內存地址等.)this

public final int getAndIncrement() {
 return unsafe.getAndAddInt(this, valueOffset, 1);
}

valueOffset
經過 unsafe.objectFieldOffset(),獲取當前 Value 這個變量在內存中的偏移量,後續會基於這個偏移量從內存中獲得value的值來和當前的值作比較,實現樂觀鎖線程

private static final long valueOffset;
static {
 try {
 valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
 } catch (Exception ex) { throw new Error(ex); }
}

getAndAddInt 經過 do/while 循環,基於 CAS 樂觀鎖來作原子遞增。實際上前面的 valueOffset 的做用就是從主內存中得到當前value 的值和預期值作一個比較,若是相等,對 value 作遞增並結束循環指針

public final int getAndAddInt(Object var1, long var2, int var4) {
 int var5;
 do {
 var5 = this.getIntVolatile(var1, var2);
 } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
 return var5;
}

get 方法
get 方法只須要直接返回 value 的值就行,這裏的 value 是經過 Volatile 修飾的,用來保證可見性code

相關文章
相關標籤/搜索