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与线程安全

相关文章
相关标签/搜索