Java.util.ConcurrentModificationException
来源:互联网 发布:数据恢复软件正式版 编辑:程序博客网 时间:2024/06/05 03:16
Java.util.ConcurrentModificationException
问题发生情景:
最近正在做数据采集相关工作,当使用gson.toJson时报错,此Crash不是100%复现,多次测试才可能出现:
E/2017-06-08 14:19:58.178 [pool-2-thread-102][CrashHandler] [TID:2676]uncaughtException msg = nullI/2017-06-08 14:19:58.178 [pool-2-thread-102][RunningRadioCrashHelper] [TID:2676] [tagRunningRecord] return false null nullE/2017-06-08 14:19:58.178 [pool-2-thread-102][CrashHandler] [TID:2676]不好,发生了异常 uncaughtException* Throwable : java.util.ConcurrentModificationException at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573) at com.elvis.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96) at com.elvis.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) at com.elvis.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.elvis.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:126) at com.elvis.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:244) at com.elvis.gson.Gson.toJson(Gson.java:671) at com.elvis.gson.Gson.toJson(Gson.java:650) at com.elvis.gson.Gson.toJson(Gson.java:605) at com.elvis.gson.Gson.toJson(Gson.java:585) at com.utest.pdm.PDMFileManager.appendPageLoadInfo(PDMFileManager.java:274) at com.utest.pdm.monitor.pageload.PageLoadMonitor$1$1.run(PageLoadMonitor.java:161) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818)
问题分析与解决:
1.查阅相关资料:
An ConcurrentModificationException is thrown when a Collection is modified and an existing iterator on the Collection is used to modify the Collection as well.—-大致意思是:ConcurrentModificationException抛出的条件是,一个迭代器在迭代集合的时候,集合被修改了
2.分析问题栈:
发现问题根源是at java.util.ArrayList执行next()函数时抛出异常,所以猜测问题的大概原因是Gson对ArrayList对象进行序列化时,ArrayList对象长度进行了更改。跟踪上层代码,代码中我们开了一个新的线程去对对象进行序列化,并且pageLoadInfo对象在父线程中还有更改的可能性。这就是问题的所在:
//保存onPause信息,倒序遍历,赋值给第一个页面(原理和 @addDrawInfo 方法类似)for (int i = pageList.size() - 1; i >= 0; i--) { final PageLoadInfo pageLoadInfo = pageList.get(i); if (pageLoadInfo.activityClassName.equals(activityClassName) && pageLoadInfo.objectHashCode.equals(objectHashCode)) { pageLoadInfo.addPauseInfo(start, end); ThreadPoolUtil.execute(new Runnable() { @Override public void run() { PDMFileManager.getInstance().appendPageLoadInfo(pageLoadInfo); } }); break; }}
3.问题解决方案:
于是我们针对业务的需求,可以将pageLoadInfo对象移除更改队列,让此对象不能再被更改。修复后的代码:
//保存onPause信息,倒序遍历,赋值给第一个页面(原理和 @addDrawInfo 方法类似)for (int i = pageList.size() - 1; i >= 0; i--) { final PageLoadInfo pageLoadInfo = pageList.get(i); if (pageLoadInfo.activityClassName.equals(activityClassName) && pageLoadInfo.objectHashCode.equals(objectHashCode)) { pageLoadInfo.addPauseInfo(start, end); //移除页面列表 pageList.remove(pageLoadInfo); //本地文件保存页面信息 ThreadPoolUtil.execute(new Runnable() { @Override public void run() { PDMFileManager.getInstance().appendPageLoadInfo(pageLoadInfo); } }); break; }}
总结:
Java.util.ConcurrentModificationException异常一定是由于对象在备操作的过程中被更改所导致的,本文所出现的问题是由于多线程同时操作同一对象导致的,查阅网上资料发现:使用List、Set、Map 时通过Iterator进行遍历,并通过集合的remove(Object) 进行删除操作,都可能引起此异常。详细请参考这篇文章: [Java ConcurrentModificationException 异常分析与解决方案]
解决问题的方法也都同一个原理,防止对象被同时操作:
1.使用Iterator提供的remove方法,用于删除当前元素
2.建一个集合,记录需要删除的元素,之后统一删除
3.使用线程安全CopyOnWriteArrayList进行删除操作
4.不使用Iterator进行遍历,需要注意的是自己保证索引正常
5.处理数据时,把数据转换为数组再进行操作
- 【ConcurrentModificationException】java.util.ConcurrentModificationException 解决办法
- java.util.ConcurrentModificationException! java.util.ConcurrentModificationException!
- java:java.util.ConcurrentModificationException
- 异常:java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException 解决办法
- java.util.ConcurrentModificationException 异常
- 异常:java.util.ConcurrentModificationException
- 异常:java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException 异常
- 【算法题】藏宝图
- java的System.getProperty()方法可以获取的值
- 移动端轮播:swiper插件(触碰图片之后停止轮播)
- 费用分摊分配用法(KSU5/KSV5/KB21N/KB11N)
- 中位数
- Java.util.ConcurrentModificationException
- bzoj 3739 DZY loves math VIII
- mysql实现编号及mysql实现排名
- jquery给某个标签如<button>等,添加点击事件,$("#XX").click(function(){ });
- Dagger2的简单使用
- SimpleDateFormat 实现 Date 和 String 之间的转换
- C# 中的委托和事件
- 你的课新媒体营销是怎么敲醒沉睡的传统卖场群体
- 消除“Permission is only granted to system apps”错误