最近需要处理一份挺大的数据,因此想到用多线程,将文件数据读到list,然后切割成n份处理,结果报了ConcurrentModificationException,大概的代码如下:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82public 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不相等就会报错,查看源代码如下:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public 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引起内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复