JAVA线程16 - 新特性:同步集合
2014-03-06 14:41
239 查看
一、概述
传统方式下的Collection在迭代集合时,不允许对集合进行修改。传统方式下用Collections工具类提供的synchronizedCollection方法来获得同步集合。分析该方法的实现源码:其实就是把方法放到同步代码块中,锁为当前集合对象。
Java5中提供了如下一些同步集合类:
通过查看java.util.concurrent包下的介绍可以知道有哪些并发集合,如:ConcurrentHashMap 、CopyOnWriteArrayList 、CopyOnWriteArraySet。
二、多线程中的集合问题
场景:有一个集合,对该集合采用迭代器进行遍历之后,又对其添加了一个元素。我们分别使用Arralist、Vector、Collections.synchronizedList、Collections.synchronizedList使用synchronized关键字进行同步控制、使用java.util.concurrent包中的高效的同步集合ConcurrentLinkedQueue进行测试。
首先创建一个任务,该任务遍历集合,又对其添加了一个元素。
public class ModifyCollectionTask implements Runnable { Collection<Integer> list; Lock lock = null; public ModifyCollectionTask(Collection<Integer> slist, Lock lock) { this.list = slist; this.lock = lock; } public void run() { //lock.lock(); //try{ // 遍历列表 for (Integer num : list) { System.out.println("线程"+Thread.currentThread().getName()+"数据为:"+num); } // 向列表添加元素 list.add(30); //}finally{lock.unlock();} } }
1. 使用ArraList集合
public class MultiThreadListTest { public static void main(String[] args) { Collection<Integer> list = new ArrayList<Integer>(); list.add(6); list.add(3); list.add(43); list.add(88); list.add(1); Lock lock = new ReentrantLock(); //启动100个线程,在多线程环境下,测试集合的同步问题 for (int i = 0; i < 100; i++) { new Thread(new ModifyCollectionTask(list, lock)).start(); } } }结果:
抛出异常:java.util.ConcurrentModificationException
说明:
常用的集合类ArrayList、Map等在多线程操作同一对象时会发生不同步的线程而造成数据读取和写入错误;通常都是采用synchronized修饰符或Lock将那些方法括起来来确保它们在执行时不会被其他线程打扰。
这样做虽然解决了数据争用问题,但是在并发性方面付出了更多的代价,因为在迭代期间锁住整个List会阻塞其他线程,使它们在很长一段时间内不能访问这个列表。
2. 使用Vector集合
public class MultiThreadListTest { public static void main(String[] args) { Collection<Integer> list = new Vector<Integer>(); list.add(6); list.add(3); list.add(43); list.add(88); list.add(1); Lock lock = new ReentrantLock(); //启动100个线程,在多线程环境下,测试集合的同步问题 for (int i = 0; i < 100; i++) { new Thread(new ModifyCollectionTask(list, lock)).start(); } } }结果:
抛出异常:java.util.ConcurrentModificationException
说明:
Vector虽然是线程同步的,但仅仅把ArrayList改成Vector还是不对。无论是ArrayList还是Vector,只要是实现Collection接口的,都要遵循fail-fast(快速失败)的检测机制,即在迭代是时候,不能修改集合的元素。一旦发现违法这个规定就会抛出异常。
事实上,Vector相对于ArrayList的线程同步,体现在对集合元素是否脏读上。即ArrayList允许脏读,而Vector特殊的机制,不会出现脏读,但是效率会很差。
3. 使用Collections工具类中的同步包装方法,将线程不安全ArrayList进行包装
public class MultiThreadListTest { public static void main(String[] args) { Collection<Integer> list = Collections.synchronizedList(new ArrayList<Integer>()); list.add(6); list.add(3); list.add(43); list.add(88); list.add(1); Lock lock = new ReentrantLock(); //启动100个线程,在多线程环境下,测试集合的同步问题 for (int i = 0; i < 100; i++) { new Thread(new ModifyCollectionTask(list, lock)).start(); } } }结果:
抛出异常:java.util.ConcurrentModificationException
说明:
对于 Collections 的 synchronizedCollection 或者 synchronizedList 方法包装过的集合来说,对于 iterator() 方法是需要用户手工进行同步的。
4. 使用java.util.concurrent包中的ConcurrentLinkedQueue高效的同步集合
将ModifyCollectionTask类中的锁相关代码注释加上,恢复到最初。public class MultiThreadListTest { public static void main(String[] args) { Collection<Integer> list = new ConcurrentLinkedQueue<Integer>(); list.add(6); list.add(3); list.add(43); list.add(88); list.add(1); Lock lock = new ReentrantLock(); //启动100个线程,在多线程环境下,测试集合的同步问题 for (int i = 0; i < 100; i++) { new Thread(new ModifyCollectionTask(list, lock)).start(); } } }结果:
没出现异常。
说明:
对于 java.util.concurrent 中的任何集合都是经过精心设计的,无论迭代、增加、删除都是线程而全的,而且在迭代时不会抛了 ConcurrentModificationException 的异常。
三、参考资料
http://blog.csdn.net/itm_hadf/article/details/7506529http://long-yu2.iteye.com/blog/1530278 http://blog.csdn.net/johnny901114/article/details/8696032
相关文章推荐
- JDK5新特性之线程同步集合(五)
- (14)多线程与并发库之java5同步集合类的应用【包含jdk1.5新特性 ConcurrentHashMap】
- JDK5新特性之线程同步集合(五)
- (14)多线程与并发库之java5同步集合类的应用【包含jdk1.5新特性 ConcurrentHashMap】
- JDK5.0 特性线程 同步装置之CountDownLatch 同步装置之CyclicBarrier 线程 BlockingQueue
- C#3.0语法新特性集合
- JDK5.0新特性系列---11.5.1线程 同步装置之Semaphore
- JAVA 集合性能特性汇总
- 19-java5同步集合类
- 11.固定集合的特性
- 利用java集合Set、Map、List等的特性,分类统计各组数据的数量
- 19.Java5同步集合类的应用
- set集合(set特性去除集合中的重复元素)
- SE6新特性之集合Set、Map、WeakSet和WeakMap详解
- JAVA高级特性之集合
- C# 3.0语言新特性(语言规范):4 对象和集合初始化器
- Elasticsearch中的索引数据Index同步到Mongodb中的集合collection中
- Collections.synchronizedXXX 集合同步
- Java集合框架官方教程(5):集合类的同步包装器/不可变包装器
- Java集合HashSet-ArrayList-HashMap的线程同步控制方法和区别