哈希图具有两个键和值对,它们不会由不同的线程并行处理。
import java.util.stream.Stream;
import java.util.Map;
import java.util.HashMap;
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.values().parallelStream()
.peek(x -> System.out.println("processing "+x+" in "+Thread.currentThread()))
.forEach(System.out::println);
}
}
输出:
processing 1 in Thread[main,5,main]
1
processing 2 in Thread[main,5,main]
2
网址:https://ideone.com/Hkxkoz
ValueSpliterator应该尝试将HashMap数组拆分为大小为1的插槽,这意味着应在不同的线程中处理两个元素。
来源:https : //www.codota.com/code/java/methods/java8.util.HMSpliterators $ ValueSpliterator /%3Cinit%3E
将它们包装后ArrayList,它会按预期工作。
new ArrayList(map.values()).parallelStream()
.peek(x -> System.out.println("processing "+x+" in "+Thread.currentThread()))
.forEach(System.out::println);
输出:
processing 1 in Thread[ForkJoinPool.commonPool-worker-3,5,main]
1
processing 2 in Thread[main,5,main]
2
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在Java中,HashMap
的并行流处理行为可能并不会如预期那样将每个元素分配到不同的线程中执行,尤其是当集合较小或者操作较快时。这是因为Java的Fork/Join框架(用于实现并行流)有一定的开销,对于小规模数据集,这个开销可能会超过并行处理带来的收益,因此它可能会选择不进行真正的并行处理,而是直接在主线程中顺序执行。
在您的示例中,直接对HashMap
的.values()
使用parallelStream()
时,两个值的处理都发生在同一个线程中,即主线程。这是因为默认的并行策略评估了任务的大小和复杂度后决定不进行拆分。
而当您将HashMap
的值放入一个新的ArrayList
后再进行并行流处理时,观察到了不同的行为,即两个元素分别在主线程和一个ForkJoinPool的工作线程中处理。这说明在这种情况下,集合转换为ArrayList
后,其并行流的拆分策略或初始化条件导致了并行处理的发生。
需要注意的是,并行处理的确切行为会受到JVM的具体实现、运行时环境、可用处理器数量等多种因素的影响,因此并不保证每次都会得到相同的结果分布。此外,Java 8及之后版本中的并行流设计主要是为了利用多核CPU提高处理大规模数据集的效率,对于小规模数据,通常建议使用顺序流以减少并行开销。
如果您希望确保在阿里云产品环境中利用并行流高效且一致地处理数据,可以考虑以下几点:
ConcurrentHashMap
这样的并发容器能更好地支持高并发下的读写操作。-Djava.util.concurrent.ForkJoinPool.common.parallelism
来调整ForkJoinPool的并行度。最后,考虑到实际应用中数据处理的复杂性和多样性,建议根据具体业务场景和性能测试结果来决定是否以及如何使用并行流。