ArrayList 線程安全問題及解決方案

前言

在提到多線程的時候咱們大都會想到ArrayList 與 HashMap,這兩個類型都是非線性安全的!在多個線程同時操做改集合對象時,會出現哪些問題呢?在傳統的集合包內的集合類到底爲何線程非安全呢?在新的JUC包類又有什麼能夠替代呢? html

介紹

①爲何ArrayList 是線性不安全的?java

②替代措施及解決方案?數組

ArrayList 咱們都知道底層是以數組方式實現的,實現了可變大小的數組,它容許全部元素,包括null。看下面一個例子:開啓多個線程操做List集合,向ArrayList中增長元素,同時去除元素。安全

import java.util.ArrayList;    
import java.util.Collections;    
import java.util.List;    
import java.util.Vector;    
    
public class ListTest {    
    // ArrayList    
    protected static ArrayList<Object> arrayList = new ArrayList<Object>();    
    
    // 解決措施①:使用Vector集合    
    protected static Vector<Object> arrayListSafe1 = new Vector<Object>();    
    
    // 解決措施②:咱們加上Collections.synchronizedList,它會自動將咱們的list方法進行改變,最後返回給咱們一個加鎖了List    
    static List<Object> arrayListSafe2 = Collections.synchronizedList(new ArrayList<Object>());    
    
    public static void main(String[] args) {    
        Thread[] threads = new Thread[500];    
        for (int i = 0; i < threads.length; i++) {    
            threads[i] = new ArrayListThread();    
            threads[i].start();    
        }    
    
        for (int i = 0; i < threads.length; i++) {    
            try {    
                threads[i].join();// 等待該線程終止    
            } catch (InterruptedException e) {    
                e.printStackTrace();    
            }    
        }    
        // 輸出list中的對象元素    
        for (int i = 0; i < threads.length; i++) {    
            System.out.println(arrayList.get(i));    
        }    
    }    
}    
    
/**  
 * 線程類,執行arrayList的add()增長方法  
 *   
 * @author zyx  
 *  
 */    
class ArrayListThread extends Thread {    
    
    @Override    
    public void run() {    
        try {    
            Thread.sleep(1000);    
        } catch (InterruptedException e) {    
            e.printStackTrace();    
        }    
        // 增長元素    
        ListTest.arrayList.add(Thread.currentThread().getName());    
    }    
    
}   
View Code

運行代碼結果可知,會出現如下幾種狀況:多線程

①Null框架

②某些線程並未打印ide

③數組下標越界異常spa

由此咱們能夠得出,在多線程狀況下操做ArrayList 並非線性安全的。那如何解決呢?.net

第一種方案:線程

使用Vertor集合

protected static Vector<Object> arrayListSafe1 = new Vector<Object>();  
View Code

第二種方案:

使用Collections.synchronizedList。它會自動將咱們的list方法進行改變,最後返回給咱們一個加鎖了List

protected static List<Object> arrayListSafe2 = Collections.synchronizedList(new ArrayList<Object>());   
View Code

第三種方案:

使用JUC中的CopyOnWriteArrayList類進行替換。具體詳情可參考JUC框架

常見集合線性是否安全可參考下圖:

List.png

 

參考文章:

ArrayList線程不安全詳解

Java中 Vector的使用詳解

Set、List、Map線程安全問題

Set與線程安全

相關文章
相關標籤/搜索