del*_*lta 6 java foreach lambda concurrentmodification
试图找出这个问题2周,但没有任何成功.:X
它发生在我进行任何类型的迭代时,但主要是在使用#forEach时.
我不是以任何方式修改列表,也不是它的元素,所以这对我来说似乎很尴尬.示例代码:
Map<Season, List<Team>> map = fetcher.getTeamsIn(ids);
Set<Team> toCreateTeams = new HashSet<>();
Set<Team> toUpdateTeams = new HashSet<>();
map.forEach((k, v) -> {
toCreateTeams.addAll(v.stream().filter(t -> !persistedTeams.containsKey(t.getId())).collect(Collectors.toSet()));
toUpdateTeams.addAll(v.stream().filter(t -> {
Date latestPersistedUpdate = persistedTeams.get(t.getId());
return latestPersistedUpdate != null && t.getLastUpdated().after(latestPersistedUpdate);
}).collect(Collectors.toSet()));
});
Run Code Online (Sandbox Code Playgroud)
map在#getTeamsIn中实例化 new HashMap<>();
试图打破eclipse中的异常,看看是否有些线程正在做一些疯狂的事情,但一切看起来都很正常.在下面的图片中,异常是在迭代时抛出map
.
我也开始有其他非常奇怪的行为,比如永远陷入lambda表达式.在这种情况下,在我看来Eclipse正在表达式中停止(出于某种未知的原因),就好像在行中设置了一些断点一样.当我暂停执行并恢复有问题的线程时,流程才会恢复正常(直到下一个lambda表达式)或一些疯狂的ConcurrentModificationException.
整个事情对我来说似乎是一些Eclipse疯狂的错误,但我真的不想重建我的环境,如果是这样的话.
我正在使用
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
Run Code Online (Sandbox Code Playgroud)
在Linux Mint上.
谢谢!
需要明确的是:即使对于这个简单的例子,错误也在发生:
map.forEach((k, v) -> {
System.out.println("Test" + k.getId());
});
Run Code Online (Sandbox Code Playgroud)
一些可能很重要的随机信息:例外仅在打印完地图的最后一个元素后才会爆炸!
关于Update 1中的随机信息,这真的不重要,因为出于性能原因(至少在HashMap和ArrayList中),ConcurrentModificationException
只在迭代结束时检查,通过比较元素数组的实际大小和预期的大小它.
#getTeamsIn方法的代码:
public Map<Season, List<Team>> getTeamsIn(List<Season> seasons) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(seasons.size());
Map<Season, List<Team>> teamsInSeason = new HashMap<>();
for (Season s : seasons) {
httpclient.execute(new HttpGet(String.format(URL, s.getId())),
new Callback(latch) {
@Override
public void completed(final HttpResponse response) {
super.completed(response);
try {
teamsInSeason.put(s, new TeamsUnmarshaller().unmarshal(response.getEntity().getContent()));
}
catch (IllegalStateException | IOException e) {
// TODO Auto-generated catch block
System.out.println(e);
}
}
});
}
latch.await();
return teamsInSeason;
}
Run Code Online (Sandbox Code Playgroud)
Callback
类刚implements FutureCallback<HttpResponse>
和countDown()
的latch
所有回调方法(#cancelled,#completed和#failed).
好吧,刚刚发现问题了。我在 #getTeamsIn 方法中重写的 #completed 方法返回时间太长(感谢 JAXB)。由于countDown()
(在 中被调用super.completed(response)
) 位于 之前teamsInSeason.put(s, new TeamsUnmarshaller().unmarshal(response.getEntity().getContent()));
,所以我们遇到了问题。
修复方法既简单又丑陋:
@Override
public void completed(final HttpResponse response) {
try {
teamsInSeason.put(s, new TeamsUnmarshaller().unmarshal(response.getEntity().getContent()));
}
catch (IllegalStateException | IOException e) {
// TODO Auto-generated catch block
System.out.println(e);
} finally {
super.completed(response);
}
}
Run Code Online (Sandbox Code Playgroud)
我认为奇怪的 Eclipse 行为(由于某种未知原因陷入某个想象的断点),如果它持续存在,那就是另一个主题的问题了。
感谢大家的帮助和时间!
归档时间: |
|
查看次数: |
2163 次 |
最近记录: |