我是靠谱客的博主 还单身帆布鞋,最近开发中收集的这篇文章主要介绍subList引起的java.util.ConcurrentModificationException原因解析,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
最近需要处理一份挺大的数据,因此想到用多线程,将文件数据读到list,然后切割成n份处理,结果报了ConcurrentModificationException,大概的代码如下:
public void execute(ExecutorContext executorContext) {
List<String> lists = Utils.readFile2List("list.txt");
lists = lists.stream().map(a -> a.replace(""", "")).collect(Collectors.toList());
// 分成n份数据来跑
int size = lists.size();
int count = size / threadNum;
int index = 0;
poolExecutor = new ThreadPoolExecutor(threadNum, threadNum,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(threadNum),
new ThreadPoolExecutor.CallerRunsPolicy());
List<Future<Map<String, Set<String>>>> futures = new ArrayList<>();
while (index < size) {
// 需新建一个list,否则操作sublist修改数据后会导致和原list modCount不相等,从而报错
List<String> subList = lists.subList(index, index + count > size? size: index+count);
futures.add(poolExecutor.submit(new DealListCall(subList, index)));
index+=count;
}
for(Future<Map<String, Set<String>>> future: futures) {
try {
Map<String, Set<String>> stringSetMap = future.get();
writefileinfo("list1", stringSetMap.get("set1"));
logger.info("index{}, list1{}", JsonUtils.objectToJson(stringSetMap.get("index")), JsonUtils
.objectToJson(stringSetMap.get("set1")));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
private class DealListCall implements Callable<Map<String, Set<String>>> {
private List<String> lists;
private int index;
public DealListCall(List<String> lists, int index) {
this.lists = lists;
this.index = index;
}
@Override
public Map<String, Set<String>> call() throws Exception {
Map<String, Set<String>> map = new HashMap<>();
Set<String> set1 = new HashSet<>();
for (int i = 0; i < 64; i++) {
int size = lists.size();
int index = 0;
// 用set来保证去重
Set<String> removelists = new HashSet<>();
Set<String> result = new HashSet<>();
while (index < size) {
long start = System.currentTimeMillis();
...
index+=1000;
logger.info("当前i{}, index{}, 耗费时间为{}", i, index, System.currentTimeMillis() - start);
}
set1.addAll(result);
lists.removeAll(removelists);
}
map.put("set1", set1);
map.put("index", set);
Thread.sleep(2000+index);
return map;
}
}
public Boolean writefileinfo(String path, Set<String> set) {
FileSystemResource resource = new FileSystemResource(path);
try {
FileWriter fileWriter = (new FileWriter(resource.getFile(), true));
for (String str : set) {
fileWriter.write(str + "n");
}
fileWriter.close();
} catch (IOException e) {
return false;
}
return true;
}
运行后报了ConcurrentModificationException,然后在网上找了一下,原因是切割list时使用了subList方法,而subList方法返回的是原list中某段数据的视图,然后ArrayList$SubList.size方法,如果原List和SubList的modCount不相等就会报错,查看源代码如下:
public E set(int index, E e) {
rangeCheck(index);
checkForComodification();
E oldValue = ArrayList.this.elementData(offset + index);
ArrayList.this.elementData[offset + index] = e;
return oldValue;
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);
}
private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
}
解决办法是新建一个list对象来包装原来的list,即new ArrayList(list1.subList(0, list1.size()))
最后
以上就是还单身帆布鞋为你收集整理的subList引起的java.util.ConcurrentModificationException原因解析的全部内容,希望文章能够帮你解决subList引起的java.util.ConcurrentModificationException原因解析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复