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

Java中的拷貝數(shù)組CopyOnWriteArrayList詳解

 更新時間:2023年12月20日 09:11:18   作者:Brain_L  
這篇文章主要介紹了Java中的拷貝數(shù)組CopyOnWriteArrayList詳解,ArrayList和LinkedList都不是線程安全的,如果需要線程安全的List,可以使用synchronizedList來生成一個同步list,但是這個同步list的方法都是通過synchronized修飾來保證同步的,需要的朋友可以參考下

CopyOnWriteArrayList詳解

ArrayList和LinkedList都不是線程安全的,如果需要線程安全的List,可以使用Collections.synchronizedList來生成一個同步list,但是這個同步list的方法都是通過synchronized修飾來保證同步的,并發(fā)性能不高。那么如何提高并發(fā)性能呢?比如某些場景下,對List的讀操作遠多于寫操作,那么CopyOnWriteArrayList就派上用場了。

1、屬性

/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;

lock是用來在寫操作時加鎖使用的,具體使用下面方法部分再看。

數(shù)組array是CopyOnWriteArrayList的核心部分了,所有的元素都存放在這個數(shù)組中。為了保證可見性,所以被volatile修飾著。

2、方法

final Object[] getArray() {
    return array;
}
final void setArray(Object[] a) {
    array = a;
}
public CopyOnWriteArrayList() {
    setArray(new Object[0]);
}
public CopyOnWriteArrayList(Collection<? extends E> c) {
    Object[] elements;
    if (c.getClass() == CopyOnWriteArrayList.class)
        elements = ((CopyOnWriteArrayList<?>)c).getArray();
    else {
        elements = c.toArray();
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elements.getClass() != Object[].class)
            elements = Arrays.copyOf(elements, elements.length, Object[].class);
    }
    setArray(elements);
}
public CopyOnWriteArrayList(E[] toCopyIn) {
    setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
}

三個構(gòu)造函數(shù)都是為了給array數(shù)組賦值,生成初始數(shù)組。

下面看下它的幾個關(guān)鍵方法:get、add、remove

private E get(Object[] a, int index) {
    return (E) a[index];
}
/**
 * {@inheritDoc}
 *
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E get(int index) {
    return get(getArray(), index);
}

get比較簡單,就是直接取數(shù)組索引處的元素。注意get方法沒有加鎖。

public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    //1、加鎖
    lock.lock();
    try {
        //2、取原數(shù)組
        Object[] elements = getArray();
        int len = elements.length;
        //3、拷貝生成新數(shù)組
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        //4、新元素加到數(shù)組最后一位
        newElements[len] = e;
        //5、數(shù)組替換
        setArray(newElements);
        return true;
    } finally {
        //6、釋放鎖
        lock.unlock();
    }
}

add方法,上來就先加鎖,然后取出原數(shù)組后拷貝生成了一個新的數(shù)組,注意,此時原有的array數(shù)組沒有變,get訪問時還是跟之前一樣。當(dāng)把新的數(shù)組替換掉array后,由于是volatile修飾的,get訪問時就會訪問添加過元素的新數(shù)組。這樣就保證了讀寫同時進行時,讀不需要加鎖依然不會有并發(fā)問題。最后釋放鎖后,別的寫操作獲得鎖,再次進行替換操作,這樣保證寫操作與寫操作之間不會有并發(fā)問題。

public E remove(int index) {
    final ReentrantLock lock = this.lock;
    //1、獲取鎖
    lock.lock();
    try {
        //2、取原數(shù)組
        Object[] elements = getArray();
        int len = elements.length;
        E oldValue = get(elements, index);
        int numMoved = len - index - 1;
        //3、如果被刪除元素是數(shù)組最后一位,直接截取len-1的新數(shù)組
        if (numMoved == 0)
            setArray(Arrays.copyOf(elements, len - 1));
        //4、否則,分段拷貝生成新數(shù)組
        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 {
        //5、釋放鎖
        lock.unlock();
    }
}

remove與add同理,也是先獲取鎖,同時生成新的數(shù)組之后再把原有的數(shù)組進行替換。

3、總結(jié)

  • 所有的元素均存儲到數(shù)組中
  • 寫操作(add/set/remove等)會改變數(shù)組結(jié)構(gòu),采用新生成一個數(shù)組然后進行替換的做法,保證了在此期間原數(shù)組可以正常訪問。同時操作之前需要先獲取鎖,避免寫操作之間產(chǎn)生并發(fā)問題。
  • 讀操作由于不需要改變數(shù)組結(jié)構(gòu),且寫操作時,對原有的數(shù)組不進行修改,此時仍可正常讀取。寫操作將新數(shù)組進行替換后,由于數(shù)組被volatile修飾,保證了可見性,此時也可正正常讀取。所以讀操作不需要加鎖。
  • 因為每次寫操作都會帶來數(shù)組拷貝,所以當(dāng)讀操作遠大于寫操作時,才可考慮使用此容器。

到此這篇關(guān)于Java中的拷貝數(shù)組CopyOnWriteArrayList詳解的文章就介紹到這了,更多相關(guān)CopyOnWriteArrayList詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • idea中增強for循環(huán)提示unexpected token問題

    idea中增強for循環(huán)提示unexpected token問題

    這篇文章主要介紹了idea中增強for循環(huán)提示unexpected token問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 使用SpringBoot編寫一個優(yōu)雅的單元測試

    使用SpringBoot編寫一個優(yōu)雅的單元測試

    這篇文章主要為大家詳細(xì)介紹了如何使用SpringBoot編寫一個優(yōu)雅的單元測試,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-07-07
  • 淺談java中文本框和文本區(qū)

    淺談java中文本框和文本區(qū)

    本文給大家介紹的是java中的文本框和文本區(qū)的概念和使用方法,以及簡單的示例,十分實用,有需要的小伙伴可以參考下。
    2015-06-06
  • Java之操作Redis案例講解

    Java之操作Redis案例講解

    這篇文章主要介紹了Java之操作Redis案例講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Spring?AOT優(yōu)化轉(zhuǎn)換的使用原理詳解

    Spring?AOT優(yōu)化轉(zhuǎn)換的使用原理詳解

    這篇文章主要介紹了Spring?AOT優(yōu)化轉(zhuǎn)換的使用原理,Spring?AOT是一種在構(gòu)建時對Spring應(yīng)用進行優(yōu)化的技術(shù),主要為GraalVM原生鏡像生成配置,同時提升傳統(tǒng)JVM的啟動性能,需要的朋友可以參考下
    2025-10-10
  • Java JDK 1.8 lambda的用法詳解

    Java JDK 1.8 lambda的用法詳解

    這篇文章主要介紹了Java JDK 1.8 lambda的用法詳解,文中給大家提到了jdk 1.8 Lambda 表達式 遍歷數(shù)組的方法,需要的朋友可以參考下
    2019-09-09
  • springboot 默認(rèn)靜態(tài)路徑實例解析

    springboot 默認(rèn)靜態(tài)路徑實例解析

    這篇文章主要介紹了springboot 默認(rèn)靜態(tài)路徑實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • 輕輕松松吃透Java并發(fā)fork/join框架

    輕輕松松吃透Java并發(fā)fork/join框架

    fork/join是一個工具框架 ,本文詳細(xì)的介紹了fork/join框架的具體使用,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Spring注解秘籍之如何優(yōu)雅地使用@RequestHeader

    Spring注解秘籍之如何優(yōu)雅地使用@RequestHeader

    @RequestHeader注解是Spring MVC中一個強大的工具,它為處理HTTP請求頭提供了一種簡潔而直觀的方法,這篇文章主要介紹了Spring注解秘籍之如何優(yōu)雅地使用@RequestHeader的相關(guān)資料,需要的朋友可以參考下
    2026-04-04
  • java使用@Transactional時常犯的N種錯誤

    java使用@Transactional時常犯的N種錯誤

    @Transactional是我們在用Spring時候幾乎逃不掉的一個注解,本文主要介紹了使用?@Transactional?時常犯的N種錯誤,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評論

莎车县| 肇东市| 绵竹市| 潮安县| 永德县| 通城县| 梅州市| 班玛县| 竹山县| 宜黄县| 延边| 乌兰察布市| 施甸县| 朝阳区| 宁波市| 合山市| 醴陵市| 虞城县| 翁牛特旗| 武汉市| 托克托县| 陆良县| 柘城县| 老河口市| 新干县| 宁化县| 遂川县| 明水县| 嘉兴市| 海宁市| 台中县| 同心县| 湟中县| 邹城市| 衡阳市| 丰城市| 花莲市| 漯河市| 永兴县| 邻水| 迁西县|