java8 concurrentmodificationexception在执行任何类型的迭代时

fae0ux8s  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(575)

我花了两个星期试图解决这个问题,但没有成功十
它发生在我进行任何类型的迭代时,但主要是在使用#foreach时。
我没有以任何方式修改列表,也没有修改它的元素,所以这对我来说非常尴尬。示例代码:

  1. Map<Season, List<Team>> map = fetcher.getTeamsIn(ids);
  2. Set<Team> toCreateTeams = new HashSet<>();
  3. Set<Team> toUpdateTeams = new HashSet<>();
  4. map.forEach((k, v) -> {
  5. toCreateTeams.addAll(v.stream().filter(t -> !persistedTeams.containsKey(t.getId())).collect(Collectors.toSet()));
  6. toUpdateTeams.addAll(v.stream().filter(t -> {
  7. Date latestPersistedUpdate = persistedTeams.get(t.getId());
  8. return latestPersistedUpdate != null && t.getLastUpdated().after(latestPersistedUpdate);
  9. }).collect(Collectors.toSet()));
  10. });

Map在#getteamsin中示例化 new HashMap<>(); 尝试在eclipse中打开异常以查看某个线程是否在做一些疯狂的事情,但在我看来一切都很正常。在下面的pics中,在迭代 map .


我也开始有一些非常奇怪的行为,比如永远陷入一个lambda表达式。在本例中,在我看来eclipse正在表达式中停止(出于某种未知的原因),就好像在行中设置了某个断点一样。当我暂停执行并只恢复有问题的线程时,流就会恢复正常(直到下一个lambda表达式)或一些疯狂的concurrentmodificationexception。

整个过程在我看来就像是一个疯狂的eclipse bug,但如果是这样的话,我真的不想重建我的环境。
我在用

  1. Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
  2. Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

在linux mint上。
谢谢!

--更新1--

要清楚的是:即使在这个简单的例子中,错误也在发生:

  1. map.forEach((k, v) -> {
  2. System.out.println("Test" + k.getId());
  3. });

一些可能很重要的随机信息:只有在打印完Map的最后一个元素之后,异常才会爆炸!

--更新2--

关于update1中的随机信息,这真的不重要,因为出于性能原因(至少在hashmap和arraylist中), ConcurrentModificationException 只有在迭代结束时,通过比较元素数组的实际大小和预期大小来检查。
方法#getteamsin的代码:

  1. public Map<Season, List<Team>> getTeamsIn(List<Season> seasons) throws InterruptedException {
  2. final CountDownLatch latch = new CountDownLatch(seasons.size());
  3. Map<Season, List<Team>> teamsInSeason = new HashMap<>();
  4. for (Season s : seasons) {
  5. httpclient.execute(new HttpGet(String.format(URL, s.getId())),
  6. new Callback(latch) {
  7. @Override
  8. public void completed(final HttpResponse response) {
  9. super.completed(response);
  10. try {
  11. teamsInSeason.put(s, new TeamsUnmarshaller().unmarshal(response.getEntity().getContent()));
  12. }
  13. catch (IllegalStateException | IOException e) {
  14. // TODO Auto-generated catch block
  15. System.out.println(e);
  16. }
  17. }
  18. });
  19. }
  20. latch.await();
  21. return teamsInSeason;
  22. }
  23. ``` `Callback` 班级公正 `implements FutureCallback<HttpResponse>` 以及 `countDown()` 这个 `latch` 在所有回调方法中(#取消、#完成和#失败)。
dtcbnfnu

dtcbnfnu1#

好的,刚刚发现问题。我在方法#getteamsin中重写的#completed方法花费的时间太长(感谢jaxb)。自从 countDown() (被召入) super.completed(response) )是在 teamsInSeason.put(s, new TeamsUnmarshaller().unmarshal(response.getEntity().getContent())); ,我们有个问题。
解决方法简单而难看:

  1. @Override
  2. public void completed(final HttpResponse response) {
  3. try {
  4. teamsInSeason.put(s, new TeamsUnmarshaller().unmarshal(response.getEntity().getContent()));
  5. }
  6. catch (IllegalStateException | IOException e) {
  7. // TODO Auto-generated catch block
  8. System.out.println(e);
  9. } finally {
  10. super.completed(response);
  11. }
  12. }

奇怪的eclipse行为(由于某种未知的原因被困在某个假想的断点中),如果它持续存在,我认为是另一个主题的问题。
谢谢大家的帮助和时间!

展开查看全部

相关问题