我正在尝试按照服务中的逻辑更新ArrayList
位置,通过Runnable在后台线程中运行。我已编辑代码以仅显示相关代码。我得到了ConcurrentModificationException
。
public static ArrayList<Location> locationPoints;
@Override
public void onLocationChanged(final Location location) {
//Log.i(TAG, "onLocationChanged: " + location);
Log.i(TAG, "onLocationChanged: " + locationPoints.size());
ArrayList<Location> alnew= locationPoints;
if(!locationPoints.isEmpty()){
for(Location l:alnew){
if(location.distanceTo(l)<=200.0f){
locationPoints.add(l);
}else{
locationPoints.add(location);
}
}
}else{
locationPoints.add(location);
}
sendLocationsToActivity(locationPoints);
}
我希望位置对象一个接一个地移动,但我看到位置对象呈指数级增长。
登录onLocationChanged
的结果如下。例外情况来自ArrayList
方法,但即使使用了此处给出的所有补救措施,我也无法找到解决方案。
onLocationChanged:0
onLocationChanged:1
onLocationChanged:2
onLocationChanged:4
onLocationChanged:8
onLocationChanged:16
onLocationChanged:32
但是,如果我从ArrayList
删除所有onLocationChanged
逻辑,只需将位置对象添加到ArrayList
,结果就是我想要的方式
onLocationChanged:0
onLocationChanged:1
onLocationChanged:2
onLocationChanged:3
onLocationChanged:4
onLocationChanged:5
堆栈跟踪:
FATAL EXCEPTION: main
Process: com.amreen.test, PID: 27053
Theme: themes:{default=overlay:com.resurrectionremix.pitchblack, fontPkg:com.resurrectionremix.pitchblack, com.android.systemui=overlay:com.resurrectionremix.pitchblack, com.android.systemui.headers=overlay:com.resurrectionremix.pitchblack, com.android.systemui.navbar=overlay:com.resurrectionremix.pitchblack}
java.util.ConcurrentModificationException
at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
at com.amreen.test.MyLocationService.onLocationChanged(MyLocationService.java:146)
at com.google.android.gms.location.internal.zzk$zzb.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5458)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
答案 0 :(得分:2)
在使用Iterator遍历列表时修改列表(添加或删除元素)时发生ConcurrentModificationException。 for-each循环只不过是java.util.Iterator的语法糖。所以这里的逻辑就像:
for() {
if(someCondition) {
locationPoints.add(sth);
}
}
而不是你可以尝试像:
for() {
if(someCondition) {
someOtherArrayList.add(sth);
}
}
一旦退出循环,那么:
locationPoints.addAll(someOtherArrayList);
答案 1 :(得分:1)
这是因为ArrayList的实现,请参考文档 ArrayList document
此类的迭代器和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过迭代器自己的remove或add方法之外,迭代器将抛出一个ConcurrentModificationException。因此,面对并发修改,迭代器会快速而干净地失败,而不是在未来不确定的时间冒着任意的,非确定性行为的风险。
您首先获得迭代器,然后使用它进行添加。 示例
Iterator<Location> iter = locationPoints.iterator(); while (iter.hasNext()) { Location location = iter.next(); if(location.distanceTo(l)<=200.0f){ iter.add(l); }else{ iter.add(location); } }