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

java并發(fā)容器CopyOnWriteArrayList實現(xiàn)原理及源碼分析

 更新時間:2017年05月22日 15:39:10   作者:dreamcatcher-cx  
這篇文章主要為大家詳細介紹了java并發(fā)容器CopyOnWriteArrayList實現(xiàn)原理及源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下

CopyOnWriteArrayList是Java并發(fā)包中提供的一個并發(fā)容器,它是個線程安全且讀操作無鎖的ArrayList,寫操作則通過創(chuàng)建底層數(shù)組的新副本來實現(xiàn),是一種讀寫分離的并發(fā)策略,我們也可以稱這種容器為"寫時復制器",Java并發(fā)包中類似的容器還有CopyOnWriteSet。本文會對CopyOnWriteArrayList的實現(xiàn)原理及源碼進行分析。

實現(xiàn)原理

  我們都知道,集合框架中的ArrayList是非線程安全的,Vector雖是線程安全的,但由于簡單粗暴的鎖同步機制,性能較差。而CopyOnWriteArrayList則提供了另一種不同的并發(fā)處理策略(當然是針對特定的并發(fā)場景)。

  很多時候,我們的系統(tǒng)應對的都是讀多寫少的并發(fā)場景。CopyOnWriteArrayList容器允許并發(fā)讀,讀操作是無鎖的,性能較高。至于寫操作,比如向容器中添加一個元素,則首先將當前容器復制一份,然后在新副本上執(zhí)行寫操作,結(jié)束之后再將原容器的引用指向新容器。

  優(yōu)缺點分析

  了解了CopyOnWriteArrayList的實現(xiàn)原理,分析它的優(yōu)缺點及使用場景就很容易了。

  優(yōu)點:

  讀操作性能很高,因為無需任何同步措施,比較適用于讀多寫少的并發(fā)場景。Java的list在遍歷時,若中途有別的線程對list容器進行修改,則會拋出ConcurrentModificationException異常。而CopyOnWriteArrayList由于其"讀寫分離"的思想,遍歷和修改操作分別作用在不同的list容器,所以在使用迭代器進行遍歷時候,也就不會拋出ConcurrentModificationException異常了

  缺點:

  缺點也很明顯,一是內(nèi)存占用問題,畢竟每次執(zhí)行寫操作都要將原容器拷貝一份,數(shù)據(jù)量大時,對內(nèi)存壓力較大,可能會引起頻繁GC;二是無法保證實時性,Vector對于讀寫操作均加鎖同步,可以保證讀和寫的強一致性。而CopyOnWriteArrayList由于其實現(xiàn)策略的原因,寫和讀分別作用在新老不同容器上,在寫操作執(zhí)行過程中,讀不會阻塞但讀取到的卻是老容器的數(shù)據(jù)。

源碼分析

  基本原理了解了,CopyOnWriteArrayList的代碼實現(xiàn)看起來就很容易理解了。

public boolean add(E e) {
  //ReentrantLock加鎖,保證線程安全
  final ReentrantLock lock = this.lock;
  lock.lock();
  try {
   Object[] elements = getArray();
   int len = elements.length;
   //拷貝原容器,長度為原容器長度加一
   Object[] newElements = Arrays.copyOf(elements, len + 1);
   //在新副本上執(zhí)行添加操作
   newElements[len] = e;
   //將原容器引用指向新副本
   setArray(newElements);
   return true;
  } finally {
   //解鎖
   lock.unlock();
  }
 } 

  添加的邏輯很簡單,先將原容器copy一份,然后在新副本上執(zhí)行寫操作,之后再切換引用。當然此過程是要加鎖的。

  刪除操作

public E remove(int index) {
  //加鎖
  final ReentrantLock lock = this.lock;
  lock.lock();
  try {
   Object[] elements = getArray();
   int len = elements.length;
   E oldValue = get(elements, index);
   int numMoved = len - index - 1;
   if (numMoved == 0)
    //如果要刪除的是列表末端數(shù)據(jù),拷貝前l(fā)en-1個數(shù)據(jù)到新副本上,再切換引用
    setArray(Arrays.copyOf(elements, len - 1));
   else {
    //否則,將除要刪除元素之外的其他元素拷貝到新副本中,并切換引用
    Object[] newElements = new Object[len - 1];
    System.arraycopy(elements, 0, newElements, 0, index);
    System.arraycopy(elements, index + 1, newElements, index,
         numMoved);
    setArray(newElements);
   }
   return oldValue;
  } finally {
   //解鎖
   lock.unlock();
  }
 }

  刪除操作同理,將除要刪除元素之外的其他元素拷貝到新副本中,然后切換引用,將原容器引用指向新副本。同屬寫操作,需要加鎖。

  我們再來看看讀操作,CopyOnWriteArrayList的讀操作是不用加鎖的,性能很高。

public E get(int index) {
  return get(getArray(), index);
 }
  直接讀取即可,無需加鎖

 private E get(Object[] a, int index) {
  return (E) a[index];
 }

 總結(jié)

  本文對CopyOnWriteArrayList的實現(xiàn)原理和源碼進行了分析,并對CopyOnWriteArrayList的優(yōu)缺點也進行了分析(Java并發(fā)包中還提供了CopyOnWriteSet,原理類似)。其實所謂并發(fā)容器的優(yōu)缺點,無非是取決于我們在面對特定并發(fā)場景時,是否能做出相對合理的選擇和應用。也希望本文能幫助到有需要的童鞋,共勉。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java內(nèi)部類應用之靜態(tài)內(nèi)部類應用示例

    Java內(nèi)部類應用之靜態(tài)內(nèi)部類應用示例

    這篇文章主要介紹了Java內(nèi)部類應用之靜態(tài)內(nèi)部類應用,結(jié)合實例形式分析了Java靜態(tài)內(nèi)部類的原理、功能、用法及相關(guān)操作注意事項,需要的朋友可以參考下
    2019-09-09
  • java 獲取當前函數(shù)名的實現(xiàn)代碼

    java 獲取當前函數(shù)名的實現(xiàn)代碼

    以下是對使用java獲取當前函數(shù)名的實現(xiàn)代碼進行了介紹。需要的朋友可以過來參考下
    2013-08-08
  • WebSocket簡介與消息推送

    WebSocket簡介與消息推送

    這篇文章介紹了WebSocket簡介與消息推送,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • java中求高精度除法,要求保留N位小數(shù)

    java中求高精度除法,要求保留N位小數(shù)

    這篇文章主要介紹了java中求高精度除法,要求保留N位小數(shù)的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java數(shù)據(jù)結(jié)構(gòu)之棧的線性結(jié)構(gòu)詳解

    Java數(shù)據(jù)結(jié)構(gòu)之棧的線性結(jié)構(gòu)詳解

    從數(shù)據(jù)結(jié)構(gòu)上看棧和隊列都是線性表,不過是兩種特殊的線性表,棧只允許在的一端進行插人或刪除操作,而隊列只允許在表的一端進行插人操作、而在另一端進行刪除操作,這篇文章主要給大家介紹了關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之棧的線性結(jié)構(gòu)的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • 詳解Mybatis中的PooledDataSource

    詳解Mybatis中的PooledDataSource

    這篇文章主要介紹了詳解Mybatis中的PooledDataSource,PooledDataSource使用了數(shù)據(jù)庫連接池可以實現(xiàn)數(shù)據(jù)庫連接池的重復利用,還能控制連接數(shù)據(jù)庫的連接上限
    2022-06-06
  • SpringBoot結(jié)合Redis實現(xiàn)序列化的方法詳解

    SpringBoot結(jié)合Redis實現(xiàn)序列化的方法詳解

    Spring提供了一個RedisTemplate來進行對Redis的操作,但是RedisTemplate默認配置的是使用Java本機序列化。如果要對對象操作,就不是那么的方便。所以本文為大家介紹了另一種SpringBoot結(jié)合Redis實現(xiàn)序列化的方法,需要的可以參考一下
    2022-06-06
  • 詳解SpringMVC 自動封裝枚舉類的方法

    詳解SpringMVC 自動封裝枚舉類的方法

    springmvc默認無法自動封裝枚舉類,本篇文章主要介紹了詳解SpringMVC 自動封裝枚舉類的方法,有興趣的可以了解一下。
    2017-04-04
  • 一文詳解Java方法重載與遞歸應用

    一文詳解Java方法重載與遞歸應用

    方法重載 允許在同一個類中定義多個具有相同名稱的方法,但 參數(shù)列表 必須不同,遞歸 是一種讓函數(shù)調(diào)用自身的技術(shù),它提供了一種將復雜問題分解為簡單問題的方法,這樣更容易解決,本文詳細介紹了Java方法重載與遞歸應用,需要的朋友可以參考下
    2024-02-02
  • SpringBoot加載多個配置文件實現(xiàn)dev、product多環(huán)境切換的方法

    SpringBoot加載多個配置文件實現(xiàn)dev、product多環(huán)境切換的方法

    這篇文章主要介紹了SpringBoot加載多個配置文件實現(xiàn)dev、product多環(huán)境切換,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03

最新評論

海兴县| 绵阳市| 高清| 双辽市| 渭源县| 肇州县| 彭州市| 高邮市| 昌都县| 贵南县| 尼勒克县| 漳浦县| 团风县| 大足县| 彭州市| 安达市| 陆良县| 大渡口区| 青田县| 南宫市| 东城区| 邵东县| 闽清县| 威宁| 泾阳县| 蒙阴县| 黑山县| 永昌县| 汽车| 沂水县| 广东省| 宝坻区| 贺州市| 溧水县| 广元市| 雷山县| 新民市| 巫溪县| 盐边县| 济南市| 永仁县|