java.util.ConcurrentModificationException

来源:互联网 发布:中国企业跨国并购数据 编辑:程序博客网 时间:2024/04/29 05:01

应用场景:
n个线程接受MQ信息(其他也一样),然后缓存到一个集合里面,消息有一个key,半小时内这个key的消息有若干,只要时间戳最大一条。
每半小时保存到数据库一次,并清除这个集合,因为高并发,接到消息直接保存,然后再删掉老数据的可行性不大。


本来以为hashtable是线程安全的,但是发现put是没有问题,但是Iterator遍历保存的时候,元素被修改了,线程是不安全的,其中元素被覆盖了,曝出了ConcurrentModificationException异常,如果仅仅是删除,Iterator提供了remove方法,倒好处理。
Iterator的next方法里面会调用 checkForComodification()判断集合是否被修改过,如果修改过就抛出ConcurrentModificationException异常
只有Hashtable本身的方法才是线程安全的,Iterator中的remove已经不是Hashtable中的方法了


1,一个解决方案是hashtable使用clone,拉出来再清空,然后针对clone出来的做遍历,这样完成了我的要求。


2,是使用ConcurrentHashMap,这是一个专门处理高并发的,不保证数据一致性,每个线程拥有自己的Iterator,这样就避免了冲突。

ConcurrentHashMap完全允许多个读操作并发进行,读操作并不需要加锁。如果使用传统的技术,
如HashMap中的实现,如果允许可以在hash链的中间添加或删除元素,读操作不加锁将得到不一致的数据。
ConcurrentHashMap的效率也很高。。。。。


3,Map map =Collections.synchronizedMap(new HashMap());  是不是可以可以保证数据一致?这个没试过。



4,LinkedBlockingQueue,ThreadPoolExecutor、好像好高深的样子,不过好像和我需求不符合,
他是如果数据多,就不断添加队列,一个队列满了就一次性执行掉。。。。。。






下面网页对原因有分析,mark一下
http://www.cnblogs.com/frankliiu-java/articles/1759460.html
http://bbs.csdn.net/topics/390139942
http://blog.csdn.net/xuweilinjijis/article/details/8651167
http://blog.csdn.net/ichsonx/article/details/5337511
http://www.iteye.com/topic/344876


0 0