最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java并發(fā)之ArrayBlockingQueue詳細介紹

 更新時間:2017年05月22日 11:07:12   投稿:lqh  
這篇文章主要介紹了java并發(fā)之ArrayBlockingQueue詳細介紹的相關(guān)資料,需要的朋友可以參考下

java并發(fā)之ArrayBlockingQueue詳細介紹

 ArrayBlockingQueue是常用的線程集合,在線程池中也常常被當做任務(wù)隊列來使用。使用頻率特別高。他是維護的是一個循環(huán)隊列(基于數(shù)組實現(xiàn)),循環(huán)結(jié)構(gòu)在數(shù)據(jù)結(jié)構(gòu)中比較常見,但是在源碼實現(xiàn)中還是比較少見的。

線程安全的實現(xiàn)

      線程安全隊列,基本是離不開鎖的。ArrayBlockingQueue使用的是ReentrantLock,配合兩種Condition,實現(xiàn)了集合的線程安全操作。這里稍微說一個好習慣,下面是成員變量的聲明。

 private static final long serialVersionUID = -817911632652898426L;
  final Object[] items;
  int takeIndex;
  int putIndex;
  int count;
  final ReentrantLock lock;
  private final Condition notEmpty;
  private final Condition notFull;
  transient Itrs itrs = null;

        賦值的操作基本都是在構(gòu)造函數(shù)里做的。這樣有個好處,代碼執(zhí)行可控。成員變量的初始化也是會合并在構(gòu)造方法里執(zhí)行的,但是在執(zhí)行順序上需要好好斟酌,如果寫在構(gòu)造方法里初始化,則沒有相關(guān)問題。

        阻塞隊列的常用場所就是生產(chǎn)者消費者。一般都是生產(chǎn)者放入,消費者從頭取數(shù)據(jù)。下面重點說這兩個操作。

        這兩個操作都是依靠鎖來保證線程安全的。

生產(chǎn)操作

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等放入操作,首先是獲取鎖,如果發(fā)現(xiàn)數(shù)據(jù)滿了,就通過notFull的condition,來阻塞線程。這里的條件判定一定是用while而不是if,多線程情況下,可以被喚醒后發(fā)現(xiàn)又滿了。

private void enqueue(E x) {
    final Object[] items = this.items;
    items[putIndex] = x;
    if (++putIndex == items.length)
      putIndex = 0;
    count++;
    notEmpty.signal();
  }

        這個是入隊列的操作。首先獲取維護的數(shù)組。putindex就是放入操作的標志。這個操作會一直加。達到預定的長度后就變成0從頭開始計數(shù)。這樣插入的操作就是一個循環(huán)的操作了,count就是用來做計數(shù)的,作為能否插入數(shù)據(jù)的一個標準,插入數(shù)據(jù)后就通過notEmpty的condition發(fā)出一個信號喚醒消費線程。

消費操作

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

        消費的方法也是這樣。先獲取鎖,然后進行條件判斷,如果沒有數(shù)據(jù),則阻塞線程。注意點和put一樣。 

  private E dequeue() {
    final Object[] items = this.items;
    @SuppressWarnings("unchecked")
    E x = (E) items[takeIndex];
    items[takeIndex] = null;
    if (++takeIndex == items.length)
      takeIndex = 0;
    count--;
    if (itrs != null)
      itrs.elementDequeued();
    notFull.signal();
    return x;
  }

        取數(shù)據(jù)的時候,也依靠takeIndex,這是一個標志,這個數(shù)值也會一直增加,表示取的第一個數(shù)據(jù)的位置。如果這個標志走到最后,然后變成0,從頭再來。這樣保證取出的數(shù)據(jù)都是fifo的順序。刪除的時候如果發(fā)現(xiàn)迭代中,則會修改迭代器的遍歷。然后通過notFull的condition來喚醒生產(chǎn)線程。

移除操作

 public boolean remove(Object o) {
    if (o == null) return false;
    final Object[] items = this.items;
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
      if (count > 0) {
        final int putIndex = this.putIndex;
        int i = takeIndex;
        do {
          if (o.equals(items[i])) {
            removeAt(i);
            return true;
          }
          if (++i == items.length)
            i = 0;
        } while (i != putIndex);
      }
      return false;
    } finally {
      lock.unlock();
    }
  }

        對于remove操作就比較麻煩了,首先獲取鎖之后,把兩個標志位本地化,然后找到要刪除的元素的位置。調(diào)用removeAt,這里刪除需要對標志位做改變。  

 void removeAt(final int removeIndex) {
    final Object[] items = this.items;
    if (removeIndex == takeIndex) {
      items[takeIndex] = null;
      if (++takeIndex == items.length)
        takeIndex = 0;
      count--;
      if (itrs != null)
        itrs.elementDequeued();
    } else {
      final int putIndex = this.putIndex;
      for (int i = removeIndex;;) {
        int next = i + 1;
        if (next == items.length)
          next = 0;
        if (next != putIndex) {
          items[i] = items[next];
          i = next;
        } else {
          items[i] = null;
          this.putIndex = i;
          break;
        }
      }
      count--;
      if (itrs != null)
        itrs.removedAt(removeIndex);
    }
    notFull.signal();
  }

        如果刪除的元素是位置和takeindex一樣。那就可以直接刪除,然后讓刪除標志位向后移動。如果不是,則從刪除的位置開始,進行后面向前面的數(shù)據(jù)覆蓋的操作。直到遇到putindex的前一個位置。然后把那個位置的數(shù)據(jù)設(shè)置為null。并且把putindex的位置往前移動一格,正在迭代的時候要刪除數(shù)據(jù)并且喚醒生產(chǎn)線程。

        感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • 關(guān)于@ConfigurationProperties注解全解析

    關(guān)于@ConfigurationProperties注解全解析

    通過@ConfigurationProperties和@ConditionalOnProperty注解,可以實現(xiàn)基于配置的條件加載Bean,以此優(yōu)化Spring Boot應(yīng)用的啟動速度,在application.yml中設(shè)置配置項,如是否加載特定的Bean(以swagger配置為例)
    2024-11-11
  • mybatis-plus配置控制臺打印完整帶參數(shù)SQL語句的實現(xiàn)

    mybatis-plus配置控制臺打印完整帶參數(shù)SQL語句的實現(xiàn)

    這篇文章主要介紹了mybatis-plus配置控制臺打印完整帶參數(shù)SQL語句,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • Spring ProtocolResolver策略接口示例

    Spring ProtocolResolver策略接口示例

    這篇文章主要介紹了Spring ProtocolResolver策略接口示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • java Unicode和UTF-8之間轉(zhuǎn)換實例

    java Unicode和UTF-8之間轉(zhuǎn)換實例

    這篇文章主要介紹了java Unicode和UTF-8之間轉(zhuǎn)換實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Java實現(xiàn)TCP互發(fā)消息

    Java實現(xiàn)TCP互發(fā)消息

    這篇文章主要為大家詳細介紹了Java實現(xiàn)TCP互發(fā)消息,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • spring中使用mybatis實現(xiàn)批量插入的示例代碼

    spring中使用mybatis實現(xiàn)批量插入的示例代碼

    這篇文章主要介紹了spring中使用mybatis實現(xiàn)批量插入的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • SpringBoot引入swagger報錯處理的解決方法

    SpringBoot引入swagger報錯處理的解決方法

    這篇文章主要給大家介紹SpringBoot引入swagger是會出現(xiàn)報錯的處理解決方法,文中有詳細的解決過程,感興趣的小伙伴可以跟著小編一起來學習吧
    2023-06-06
  • java算法實現(xiàn)紅黑樹完整代碼示例

    java算法實現(xiàn)紅黑樹完整代碼示例

    這篇文章主要介紹了java算法實現(xiàn)紅黑樹完整代碼示例,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • java發(fā)送http的get、post請求實現(xiàn)代碼

    java發(fā)送http的get、post請求實現(xiàn)代碼

    下面小編就為大家?guī)硪黄猨ava發(fā)送http的get、post請求實現(xiàn)代碼。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05
  • 解決springboot jpa @Column columnDefinition等屬性失效問題

    解決springboot jpa @Column columnDefinition等屬性失效問題

    這篇文章主要介紹了解決springboot jpa @Column columnDefinition等屬性失效問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10

最新評論

保靖县| 长泰县| 随州市| 韶关市| 茂名市| 福泉市| 旅游| 永福县| 亳州市| 鞍山市| 瑞昌市| 洛阳市| 平乡县| 内江市| 乐昌市| 仁怀市| 万荣县| 贵阳市| 公主岭市| 斗六市| 青田县| 彰化县| 安远县| 蒲城县| 拉孜县| 南丰县| 勐海县| 延寿县| 台北市| 张家口市| 德保县| 陈巴尔虎旗| 双城市| 西乌珠穆沁旗| 象山县| 曲水县| 沈丘县| 沙坪坝区| 德保县| 永宁县| 彩票|