You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Dispatchers.Default中操作列表遇ConcurrentModificationException需拆分代码块吗?

解决Dispatchers.Default中列表操作引发的ConcurrentModificationException问题

问题分析

你遇到的java.util.ConcurrentModificationException,核心原因不是把更新和排序放在同一个Dispatchers.Default块里,而是当前代码的迭代方式存在风险,或者listOfLocation被其他线程/协程并发修改了:

  • 你用for (item in listOfLocation)的方式迭代列表,这种迭代依赖于列表的迭代器,而迭代器会维护内部的修改计数。如果迭代过程中通过indexOf定位元素并替换(尤其是当列表存在重复元素时,indexOf可能返回错误索引),或者其他线程同时修改了列表结构,就会触发异常。
  • 拆分到两个独立的Dispatchers.Default块完全没必要,反而可能因为中间其他线程介入修改列表,加重并发问题。

修复方案

1. 改用索引迭代,避免迭代器冲突

把迭代方式换成基于索引的循环,直接通过下标访问和替换元素,彻底规避迭代器的修改计数校验问题:

withContext(Dispatchers.Default) {
    for (i in listOfLocation.indices) {
        val item = listOfLocation[i]
        val distanceInMeter = ClsGlobel.calculateDistance(
            item.lat, item.lon, it.latitude, it.longitude
        ) * 1000
        listOfLocation[i] = SavedLocation(item.id, item.lat, item.lon, distanceInMeter, item.areaName)
    }

    listOfLocation.sortBy { it.distance }
    Log.e("tag", " Default: " + Thread.currentThread().name)
}

2. 确保列表的线程安全性

如果listOfLocation会被多个线程/协程同时读写,必须使用线程安全的集合(比如CopyOnWriteArrayList),或者在所有访问该列表的代码块中加锁(比如用synchronized),避免并发修改。

总结

不需要拆分更新和排序的逻辑到两个Dispatchers.Default块里。调整迭代方式,同时保证列表不会被并发修改,就能解决ConcurrentModificationException异常。

内容的提问来源于stack exchange,提问作者karan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 16:16:10