1. 程式人生 > 其它 >hibernate 併發獲取session失敗 空指標_「Java併發」LinkedBlockingQueue-執行緒安全等級

hibernate 併發獲取session失敗 空指標_「Java併發」LinkedBlockingQueue-執行緒安全等級

技術標籤:hibernate 併發獲取session失敗 空指標

81583b3b5b1561e865d26c26161ce224.png LinkedBlockingQueue1.BlockingQueue定義的常用方法如下BlockingQueue的幾個注意點簡要概述BlockingQueue常用的四個實現類LinkedBlockQueue原始分析

LinkedBlockingQueue

由於LinkedBlockingQueue實現是執行緒安全的,實現了先進先出等特性,是作為生產者消費者的首選

LinkedBlockingQueue,其中主要是用到和拿取方法,把方法放在串聯的時候會一直到有集體成員被消費,拿走方法在當時空的時候會一直到,直到有一部分成員被放進來。

BlockingQueue不接受null元素。null被用作指示輪詢操作失敗的警戒值。

BlockingQueue位於jucpack,常用語言併發的生產者,消費者場景,與普通佇列排序,增加兩個put,take操作:獲取元素時等待變為非空,以及儲存元素時等待空間變得可用。

1.BlockingQueue定義的常用方法如下

-丟擲異常布林/空雙面超時插入加(e)報價放報價(時間,單位)移除並返回去掉()輪詢()採取()民意測驗(時間,單位)返回不移除元件()窺視()--

BlockingQueue的幾個注意點

  • 1,BlockingQueue可以是限定容量的:可以指定容量,也可以不指定,不指定的話,至少最大是Integer.MAX_VALUE
  • 2,BlockingQueue實現主要用於生產者-使用者人數
  • 3,BlockingQueue實現是執行緒安全的

簡要概述BlockingQueue常用的四個實現類

  • ArrayBlockingQueue:規定大小的BlockingQueue,其建構函式必須帶一個int引數來指定其大小。其所含的物件具有FIFO(先入先出)順序排序的。
  • LinkedBlockingQueue:大小不定的BlockingQueue,若其建構函式帶一個規定大小的引數,生成的BlockingQueue有大小限制,若不帶大小引數,所生成的BlockingQueue的大小由Integer.MAX_VALUE來決定。其所含的物件是以FIFO(先入先出)順序排序的
  • PriorityBlockingQueue:連結LinkedBlockQueue,但其所含物件的排序不是FIFO,而是依據物件的自然排序或者是建構函式的Comparator決定的順序。
  • SynchronousQueue:特殊的BlockingQueue,進行的操作必須是放和取交替完成的。

其中LinkedBlockingQueue和ArrayBlockingQueue比較起來,它們背後所用的資料結構不一樣(分別通過陣列,連結串列方式實現),導致LinkedBlockingQueue的資料總量要大於ArrayBlockingQueue,但線上程數量很大時其效能的可預見性有所降低ArrayBlockingQueue。

LinkedBlockQueue原始分析

  • 名義節點,內部類別:Node是佇列的一個內部類,代表中間中一個節點,此中斷補單包含儲存的物件值,還包含一個指向下一個計數器的引用,這樣第一個中斷,指向第二個,一次類推,形成一個似乎鏈條一樣的鏈。第一個元素附著:頭,最後一個副本:尾,如果只有一個元素即是頭又是尾。
  • 建構函式預設建立Integer.MAX_VALUE容量的本質,頭元素和尾元素指向同一個沒有值的Node。
  • 放方法
public void put(E e) throws InterruptedException { // 不接受null值 if (e == null) throw new NullPointerException(); // Note: convention in all put/take/etc is to preset local var // holding count negative to indicate failure unless set. int c = -1; Node node = new Node(e); // 寫入鎖 (因為讀寫操作隊頭隊尾,需要兩把鎖) final ReentrantLock putLock = this.putLock; // 容量計步器 final AtomicInteger count = this.count; putLock.lockInterruptibly(); try { /* * Note that count is used in wait guard even though it is * not protected by lock. This works because count can * only decrease at this point (all other puts are shut * out by lock), and we (or some other waiting put) are * signalled if it ever changes from capacity. Similarly * for all other uses of count in other wait guards. */ // 佇列慢,阻塞 while (count.get() == capacity) { notFull.await(); } // 新增元素 ( 隊尾的last指標指向新新增的元素 ) enqueue(node); // 容量計步器+1 c = count.getAndIncrement(); // 容量未滿,通知notFull if (c + 1 < capacity) notFull.signal(); } finally { putLock.unlock(); } if (c == 0) signalNotEmpty();}
  • 取方法
    ```
    公共電子取()丟擲InterruptedException的{
    E X;
    int c = -1;
    //容量計步器
    final AtomicInteger count = this.count;
    //
    最終將資料獲取鎖ReentrantLock takeLock = this.takeLock;
    takeLock.lockInterruptible();
    嘗試{ // 佇列為空,阻塞並等待 while (count.get() == 0) { notEmpty.await(); } // 佇列不為空,返回對頭元素,隊頭指標置空 x = dequeue(); // 容量計步器-1 c = count.getAndDecrement(); // 容量為空,通知notEmpty if (c > 1) notEmpty.signal();}最後{ takeLock.unlock();}
    如果(C ==容量) signalNotFull();返回x;
    }

// //可移除隊頭元素並返回
private E dequeue(){
// assert takeLock.isHeldByCurrentThread();
//斷言head.item == null;
節點h =頭
節點首先= h.next;
h.next = h; //幫助GC
head = first;
E x = first.item;
first.item = null;
返回x;
}

##### ArrayBlocklingQueue 原始碼分析與普通佇列相比,其put、take方法法支援阻塞,下面看下這兩個方法原始碼如下:- put

public void put(E)丟擲InterruptedException {
//不接受null值
checkNotNull(e);
//獲取鎖
最終的ReentrantLock lock = this.lock;
lock.lockInterruptible();
嘗試{
//容量滿,二進位制,通知notFull,
而(count == items.length)
notFull.await();
//新增元素
insert(e);
}最後{
lock.unlock();
}
}

//新增一個元素
private void insert(E x){
items [putIndex] = x;
putIndex = inc(putIndex);
++ count;
notEmpty.signal();
}

- take

public E take()throws InterruptedException {
//獲取鎖
最終ReentrantLock lock = this.lock;
lock.lockInterruptible();
嘗試{
//容量未空,每秒
while(count == 0)notEmpty.await
();
//移除並返回元素
return extract();
}最後{
//釋放鎖
lock.unlock();
}
}
``

從上面的簡單二進位制分析看,連結串列,複製實現程式的空值流程基本一致,獲取鎖,新增,可刪除元素,釋放鎖,唯一不同點在於連結串列內部維護指標,內部維護索引,具體採用哪一個更好,還是根據業務場景,看兩者的put,take方法的時間複雜度。

d3e555b9d58e94cd7d48b7738fe6d642.png