在提到多线程的时候咱们大都会想到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()); } }
运行代码结果可知,会出现如下几种状况:多线程
①Null框架
②某些线程并未打印ide
③数组下标越界异常spa
由此咱们能够得出,在多线程状况下操做ArrayList 并非线性安全的。那如何解决呢?.net
第一种方案:线程
使用Vertor集合
protected static Vector<Object> arrayListSafe1 = new Vector<Object>();
第二种方案:
使用Collections.synchronizedList。它会自动将咱们的list方法进行改变,最后返回给咱们一个加锁了List
protected static List<Object> arrayListSafe2 = Collections.synchronizedList(new ArrayList<Object>());
第三种方案:
使用JUC中的CopyOnWriteArrayList类进行替换。具体详情可参考JUC框架
常见集合线性是否安全可参考下图:
参考文章: