List集合相信大家都经常用吧,但是可惜的是它不是线程安全的,那么,该如何把list变成一个线程安全的集合呢?下面就来看看吧。
首先我们知道,ArrayList不是一个线程安全的集合,因此在实现多线程开发时,我们不能够使用多个线程同时操作List。如果我们让一个线程向 ArrayList中添加元素,又让另一个线程从其中删除元素,就会出现线程安全问题,抛出ConcurrentModificationException异常。
Vector
我们要知道Vector,这是一个可变长度的数组,它类似于ArrayList,但与ArrayList不同,Vector是绝对线程安全的,它的机制就是会给几乎所有的public方法都加上synchronized关键字。但是,由于加锁会导致性能降低到一定程度,在不需要并发访问同一对象时,像这样强制性的同步机制就显得非常多余了,所以Vector现在已经被抛弃啦。
Collections
但是办法总是想出来的,在Vector和HashTable相继被弃用后,它们被ArrayList及HashMap代替,但ArrayList及HashMap它们不是线程安全的,所以java中就有了Collections这么一个工具类,它能够提供相应的包装方法把ArrayList和HashMap包装成线程安全的集合。实现代码如下:
ListsynArrayList = Collections.synchronizedList(new ArrayList());
读写速度测试:
import java.util.*; import java.util.Collections; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; /** * * @author tanhuiling *Collections.synchronizedList和CopyOnWriteArrayList性能分析 */ public class ListTest { private static List < String > arrayList = Collections.synchronizedList(new ArrayList < String > ()); private static List < String > copyOnWriteArrayList = new CopyOnWriteArrayList < String > (); private static CountDownLatch cdl1 = new CountDownLatch(2); private static CountDownLatch cdl2 = new CountDownLatch(2); private static CountDownLatch cdl3 = new CountDownLatch(2); private static CountDownLatch cdl4 = new CountDownLatch(2); //ArrayList写线程 static class ArrayAddThread extends Thread { @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 50000; i++) { arrayList.add(String.valueOf(i)); } cdl1.countDown(); } } //ArrayList读线程 static class ArrayGetThread extends Thread { @Override public void run() { // TODO Auto-generated method stub int size = arrayList.size(); for (int i = 0; i < size; i++) { arrayList.get(i); } cdl2.countDown(); } } //CopyOnWriteArrayList写线程 static class CopyAddThread extends Thread { @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 50000; i++) { copyOnWriteArrayList.add(String.valueOf(i)); } cdl3.countDown(); } } //CopyOnWriteArrayList写线程 static class CopyGetThread extends Thread { @Override public void run() { // TODO Auto-generated method stub int size = copyOnWriteArrayList.size(); for (int i = 0; i < size; i++) { copyOnWriteArrayList.get(i); } cdl4.countDown(); } } public static void main(String[] args) throws InterruptedException { long start1 = System.currentTimeMillis(); new ArrayAddThread() .start(); new ArrayAddThread() .start(); cdl1.await(); long end1 = System.currentTimeMillis(); System.out.println("ArrayList写操作时间:" + (end1 - start1)); long start3 = System.currentTimeMillis(); new CopyAddThread() .start(); new CopyAddThread() .start(); cdl3.await(); long end3 = System.currentTimeMillis(); System.out.println("CopyOnWriteArrayList的写操作时间:" + (end3 - start3)); long start2 = System.currentTimeMillis(); new ArrayGetThread() .start(); new ArrayGetThread() .start(); cdl2.await(); long end2 = System.currentTimeMillis(); System.out.println("ArrayList读操作时间:" + (end2 - start2)); long start4 = System.currentTimeMillis(); new CopyGetThread() .start(); new CopyGetThread() .start(); cdl4.await(); long end4 = System.currentTimeMillis(); System.out.println("CopyOnWriteArrayList的读操作时间:" + (end4 - start4)); } }
结果:
ArrayList写操作时间:30 CopyOnWriteArrayList的写操作时间:5710 ArrayList读操作时间:28 CopyOnWriteArrayList的读操作时间:2
以上就是关于list实现线程安全的所有内容啦,如果还想要知道更多像list这样的java常见问答知识的话,就快来关注我们的网站了解吧。
推荐阅读: