中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

通過Java源碼解析阻塞隊列ArrayBlockingQueue

發布時間:2021-08-31 09:46:18 來源:億速云 閱讀:96 作者:chen 欄目:編程語言

本篇內容主要講解“通過Java源碼解析阻塞隊列ArrayBlockingQueue”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“通過Java源碼解析阻塞隊列ArrayBlockingQueue”吧!

Java的阻塞隊列,在實現時,使用到了lock和condition,下面是對其主要方法的介紹。

首先看一下,阻塞隊列中使用到的鎖。

/** Main lock guarding all access **/
  final ReentrantLock lock;
  /** Condition for waiting takes **/
  private final Condition notEmpty;
  /** Condition for waiting puts **/
  private final Condition notFull;

主要的鎖是一個可重入鎖,根據注釋,它是用來保證所有訪問的同步。此外,還有2個condition,notEmpty用于take等待,notFull用于put等待。

兩個condition的初始化方法如下:

public ArrayBlockingQueue(int capacity, boolean fair) {
    if (capacity <= 0)
      throw new IllegalArgumentException();
    this.items = new Object[capacity];
    lock = new ReentrantLock(fair);
    notEmpty = lock.newCondition();
    notFull = lock.newCondition();
  }

下面介紹一下put方法。代碼如下。

public void put(E e) throws InterruptedException {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
      while (count == items.length)
        notFull.await();
      enqueue(e);
    } finally {
      lock.unlock();
    }
  }

進行put時,首先對待插入的元素進行了非null判斷。然后獲取鎖。之后用一個循環進行判斷,如果元素已滿,那么,就調用notFull的await方法,進行阻塞。當有別的線程(其實是take元素的線程)調用notFull的siginal方法后,put線程會被喚醒。喚醒后再確認一下count是否小于items.length,如果是,則進行加入隊列的操作。

下面介紹一下take方法,代碼如下:

public E take() throws InterruptedException {
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
      while (count == 0)
        notEmpty.await();
      return dequeue();
    } finally {
      lock.unlock();
    }
  }

進行take時,同樣先要獲取鎖,然后判斷元素個數是否為0,為0時需要等待在notEmpty條件上,等待被喚醒。喚醒之后,會再進行一次元素個數判斷,然后進行出隊列操作。

分析代碼到這里的時候,我產生了一個疑問,如果當前隊列慢了,執行put的線程在獲取到鎖之后,等待notFull條件上。那么,當執行take操作的線程想獲取鎖時,阻塞隊列的鎖已經被前面put的線程獲取了,那么take將永遠得不到機會執行。怎么回事呢?

后來,我查了condition的await方法,它的注釋如下:

  • Causes the current thread to wait until it is signalled or interrupted.

  • The lock associated with this Condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens......

原因在await方法的作用上。因為condition是通過lock創建的,而調用condition的await方法時,會自動釋放和condition關聯的鎖。所以說,當put線程被阻塞后,它實際已經釋放了鎖了。所以,當有take線程想執行時,它是可以獲取到鎖的。

另一個問題:當等待在condition上的線程被喚醒時,因為之前調用await前,已經獲取了鎖,那么被喚醒時,它是自動就擁有了鎖,還是需要重新獲取呢?

在await方法的注釋中,有如下的一段話:

  • In all cases, before this method can return the current thread must re-acquire the lock associated with this condition. When the thread returns it is guaranteed to hold this lock.

說明當等待在condition上的線程被喚醒時,它需要重新獲取condition關聯的鎖,獲取到之后,await方法才會返回。

到此,相信大家對“通過Java源碼解析阻塞隊列ArrayBlockingQueue”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

灯塔市| 武宁县| 潞西市| 双牌县| 曲麻莱县| 武强县| 乌海市| 昌宁县| 潞西市| 宁武县| 乌鲁木齐市| 伊宁市| 宁陕县| 潮州市| 田东县| 宁德市| 军事| 垦利县| 大理市| 乐清市| 盐池县| 舟山市| 宾川县| 岳普湖县| 新丰县| 河池市| 衡阳市| 德昌县| 井研县| 三原县| 南木林县| 安顺市| 琼海市| 十堰市| 改则县| 水城县| 新邵县| 南皮县| 前郭尔| 南雄市| 牙克石市|