java - 这个 IntStream 分区实现真的不是线程安全的吗?
问题描述
此答案提供了对 IntStream 进行分区的实现:
IntStream intStream = IntStream.iterate(0, i -> i + 1).limit(1000000);
Predicate<Integer> p = x -> r.nextBoolean();
Map<Boolean, List<Integer>> groups = intStream.collect(() -> {
Map<Boolean, List<Integer>> map = new HashMap<>();
map.put(false, new ArrayList<>());
map.put(true, new ArrayList<>());
return map;
}, (map, x) -> {
boolean partition = p.test(x);
List<Integer> list = map.get(partition);
list.add(x);
}, (map1, map2) -> {
map1.get(false).addAll(map2.get(false));
map1.get(true).addAll(map2.get(true));
});
System.out.println(groups.get(false).size());
System.out.println(groups.get(true).size());
但是它的编辑提到这个实现不是线程安全的。然而,据我所见,收集器HashMap<List<Integer>>
为并行流中的每个线程创建了一个单独的线程。所以每个地图都被限制在一个线程中。分区功能也仅限于单个线程。合并函数合并来自多个线程的结果,但据我所知,流框架确保合并以线程安全的方式完成。所以我的问题是:这个解决方案真的不是线程安全的吗?
顺便说一句:无论如何,答案提供了一个更优雅的解决方案(Stream<Integer> stream = intStream.boxed();
等),但我仍然想知道。
PS:我想将此问题添加为原始帖子的评论,但我什至没有添加评论的声誉......:|
解决方案
根据 Oracles 文档
与 reduce(int, IntBinaryOperator) 一样,collect 操作可以并行化,无需额外同步。
所以看起来你的直觉是正确的,这是线程安全的。
推荐阅读
- java - 从另一个窗口对一个窗口的元素执行 JavaFX 操作
- javascript - aframe-physics-system.js:5508 Uncaught TypeError: Cannot read property 'x' of undefined
- android - 转到另一个页面后删除欢迎页面
- azure-devops - Artifact feed azure devops.Not sure how it meant to work
- angular - Angular Material Tree nested node depth
- unit-testing - 具有良好测试的 TYPO3 扩展
- r - R中的循环向量返回
- git - 如何用原始存储库更新我的本地分支分支,我从中分叉了本地存储库的主分支?
- arm - DS5 Ultimate 版本在访问传递给 asm 调用的第一个浮点参数时的不同行为
- google-apps-script - Modify Google App Script - Gmail to Google Drive