guava包中数组切割方法Lists.patitions采坑记 :异常java.util.ConcurrentModificationException
背景
先来说一下背景:业务中有个场景需要批量操作某个originList,当originList中的元素过多(超过10),考虑到系统RT值的问题,需要切割originList,然后用多线程的方式来异步请求,处理每个itemList。
错误代码示例
public static void main(String[] args) throws Exception {
List<Long> originList = Lists.newArrayList();
for (int i = 0; i < 100; i++) {
originList.add(Long.valueOf(i));
}
List<List<Long>> splitLists = Lists.partition(originList, 10);
// 通过线程池的方式,启动10个线程来分别处理每个切割后的数组
ExecutorService executors = Executors.newFixedThreadPool(10);
splitLists.forEach(itemList ->
executors.execute(() -> {
try {
// 对每个itemList根据业务诉求进行增删改的操作
itemList.set(1, 1L);
itemList.remove(2);
System.out.println("scuess");
} catch (Exception e) {
e.printStackTrace();
System.out.println("error");
}
})
);
executors.shutdownNow();
}
问题分析
按照预期,业务代码中对itemList进行下列操作时,是不会有任务异常的。
itemList.set(1, 1L);
itemList.remove(2);
因为其 只是对单个的itemList元素进行操作,是不存在并发竞争同一资源的情况。
因此,我期待输出的是十个“success”才对。
实际上,却抛了java.util.ConcurrentModificationException异常。且多次尝试,输出“success”和“error”的次数并不固定。
java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1237)
at java.util.ArrayList$SubList.set(ArrayList.java:1033)
at com.jszhao.demo.map.ListsDemo.lambda$null$0(ListsDemo.java:24