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

ArrayList源碼和多線程安全問題分析

 更新時間:2019年05月29日 11:34:31   作者:NULL  
這篇文章主要介紹了ArrayList源碼和多線程安全問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,下面小編和大家一起來學(xué)習(xí)一下吧

1.ArrayList源碼和多線程安全問題分析

在分析ArrayList線程安全問題之前,我們線對此類的源碼進行分析,找出可能出現(xiàn)線程安全問題的地方,然后代碼進行驗證和分析。

1.1 數(shù)據(jù)結(jié)構(gòu)

ArrayList內(nèi)部是使用數(shù)組保存元素的,數(shù)據(jù)定義如下:

transient Object[] elementData; // non-private to simplify nested class access

在ArrayList中此數(shù)組即是共享資源,當(dāng)多線程對此數(shù)據(jù)進行操作的時候如果不進行同步控制,即有可能會出現(xiàn)線程安全問題。

1.2 add方法可能出現(xiàn)的問題分析

首先我們看一下add的源碼如下:

public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}

此方法中有兩個操作,一個是數(shù)組容量檢查,另外就是將元素放入數(shù)據(jù)中。我們先看第二個簡單的開始分析,當(dāng)多個線程執(zhí)行順序如下所示的時候,會出現(xiàn)最終數(shù)據(jù)元素個數(shù)小于期望值。

按照此順序執(zhí)行完之后,我們可以看到,elementData[n]的只被設(shè)置了兩次,第二個線程設(shè)置的值將前一個覆蓋,最后size=n+1。下面使用代碼進行驗證此問題。

1.3 代碼驗證

首先先看下以下代碼,開啟1000個線程,同時調(diào)用ArrayList的add方法,每個線程向ArrayList中添加100個數(shù)字,如果程序正常執(zhí)行的情況下應(yīng)該是輸出:

list size is :10000

代碼如下:

private static List<Integer> list = new ArrayList<Integer>();
private static ExecutorService executorService = Executors.newFixedThreadPool(1000);
private static class IncreaseTask extends Thread{
@Override
public void run() {
System.out.println("ThreadId:" + Thread.currentThread().getId() + " start!");
for(int i =0; i < 100; i++){
list.add(i);
}
System.out.println("ThreadId:" + Thread.currentThread().getId() + " finished!");
}
}
public static void main(String[] args){
for(int i=0; i < 1000; i++){
executorService.submit(new IncreaseTask());
}
executorService.shutdown();
while (!executorService.isTerminated()){
try {
Thread.sleep(1000*10);
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println("All task finished!");
System.out.println("list size is :" + list.size());
}

當(dāng)執(zhí)行此main方法后,輸出如下:

從以上執(zhí)行結(jié)果來看,最后輸出的結(jié)果會小于我們的期望值。即當(dāng)多線程調(diào)用add方法的時候會出現(xiàn)元素覆蓋的問題。

1.4 數(shù)組容量檢測的并發(fā)問題

在add方法源碼中,我們看到在每次添加元素之前都會有一次數(shù)組容量的檢測,add中調(diào)用此方法的源碼如下:

ensureCapacityInternal(size + 1);

容量檢測的相關(guān)源碼如下:

private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

容量檢測的流程圖如下所示:

我們以兩個線程執(zhí)行add操作來分析擴充容量可能會出現(xiàn)的并發(fā)問題:
當(dāng)我們新建一個ArrayList時候,此時內(nèi)部數(shù)組容器的容量為默認容量10,當(dāng)我們用兩個線程同時添加第10個元素的時候,如果出現(xiàn)以下執(zhí)行順序,可能會拋出java.lang.ArrayIndexOutOfBoundsException異常。

第二個線程往數(shù)組中添加數(shù)據(jù)的時候由于數(shù)組容量為10,而此操作往index為10的位置設(shè)置元素值,因此會拋出數(shù)組越界異常。

1.5 代碼驗證數(shù)組容量檢測的并發(fā)問題

使用如下代碼:

private static List<Integer> list = new ArrayList<Integer>(3);
private static ExecutorService executorService = Executors.newFixedThreadPool(10000);
private static class IncreaseTask extends Thread{
@Override
public void run() {
System.out.println("ThreadId:" + Thread.currentThread().getId() + " start!");
for(int i =0; i < 1000000; i++){
list.add(i);
}
System.out.println("ThreadId:" + Thread.currentThread().getId() + " finished!");
}
}
public static void main(String[] args){
new IncreaseTask().start();
new IncreaseTask().start();
}

執(zhí)行main方法后,我們可以看到控制臺輸出如下:

1.6 ArrayList中其他方法說明

ArrayList中其他包含對共享變量操作的方法同樣會有并發(fā)安全問題,只需要按照以上的分析方法分析即可。

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

相關(guān)文章

  • Bean的自動注入及循環(huán)依賴問題

    Bean的自動注入及循環(huán)依賴問題

    本文詳細介紹了Bean的自動注入及循環(huán)依賴,文中通過代碼介紹的非常詳細,對大家的學(xué)習(xí)有一定的研究價值,感興趣的小伙伴可以閱讀參考
    2023-03-03
  • Java selenium上傳文件的實現(xiàn)

    Java selenium上傳文件的實現(xiàn)

    本文主要介紹了Java selenium上傳文件的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Java Poi 在Excel中輸出特殊符號的實現(xiàn)方法

    Java Poi 在Excel中輸出特殊符號的實現(xiàn)方法

    這篇文章主要介紹了Java Poi 在Excel中輸出特殊符號的實現(xiàn)方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • spring boot使用WebClient調(diào)用HTTP服務(wù)代碼示例

    spring boot使用WebClient調(diào)用HTTP服務(wù)代碼示例

    這篇文章主要介紹了spring boot使用WebClient調(diào)用HTTP服務(wù)代碼示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • 基于java實現(xiàn)簡單的圖片類別識別

    基于java實現(xiàn)簡單的圖片類別識別

    這篇文章主要為大家詳細介紹了如何基于java實現(xiàn)簡單的圖片類別識別功能,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • 往DAO類中注入@PersistenceContext和@Resource的區(qū)別詳解

    往DAO類中注入@PersistenceContext和@Resource的區(qū)別詳解

    這篇文章主要介紹了往DAO類中注入@PersistenceContext和@Resource的區(qū)別詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Spring?Cloud?整合?nacos實現(xiàn)動態(tài)配置中心的詳細步驟

    Spring?Cloud?整合?nacos實現(xiàn)動態(tài)配置中心的詳細步驟

    這篇文章主要介紹了Spring?Cloud?整合?nacos?實現(xiàn)動態(tài)配置中心,整合步驟是通過添加依賴新建nacos配置,本文分步驟通過實例代碼給大家詳細講解,需要的朋友可以參考下
    2022-10-10
  • Spring Boot項目利用Redis實現(xiàn)session管理實例

    Spring Boot項目利用Redis實現(xiàn)session管理實例

    本篇文章主要介紹了Spring Boot項目利用Redis實現(xiàn)session管理實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Spring?加載?Application?Context五種方式小結(jié)

    Spring?加載?Application?Context五種方式小結(jié)

    這篇文章主要介紹了Spring?加載?Application?Context五種方式小結(jié),具有很好的參考價值,希望對大家有所幫助。
    2022-01-01
  • Spring中ClassPath指的是哪些地方

    Spring中ClassPath指的是哪些地方

    在Spring應(yīng)用中,ClassPath指的是應(yīng)用程序的類加載路徑,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06

最新評論

蓬莱市| 天台县| 锦州市| 宜宾市| 汪清县| 江都市| 西华县| 台前县| 莒南县| 淅川县| 永川市| 嘉峪关市| 抚顺县| 神池县| 高尔夫| 漾濞| 定日县| 萝北县| 蛟河市| 兰坪| 鄂州市| 平和县| 汉寿县| 和田县| 磴口县| 永胜县| 济宁市| 吉林市| 泾阳县| 富源县| 安陆市| 镇坪县| 永修县| 兰溪市| 正蓝旗| 米脂县| 神农架林区| 喀喇沁旗| 镇坪县| 车致| 鹤壁市|