【问题标题】:Java parallel Streams processing time mismatchJava 并行 Streams 处理时间不匹配
【发布时间】:2020-08-03 12:13:06
【问题描述】:

在我的 windows 机器上,我有 6 个内核。

我创建了一个包含 24 个元素的流,并使用 Stream API 中的 map 操作对每个元素执行操作。我利用并行性:

myCollection.parallelStream()
                    .map(element -> someTimeConsumingOperation(element)
                    .collect(toList());

someTimeConsumingOperation 使用以下方法模拟长时间操作:

Thread.sleep(2000);

myCollection 有 24 个元素。我知道流使用默认的 ForkJoinPool 执行器来并行运行操作,这反过来又会考虑内核数来确定池中有多少线程。

由于有 6 个内核,所以我假设最多创建 6 个线程。如果是这种情况,并且每个操作需要将近 2 秒,那么整个流处理必须花费大约 8 秒(每个线程将执行 4 个操作,因为我们有 24 个元素要处理,因此需要 4*2 秒)。

但我观察到处理只需要 4 秒。

【问题讨论】:

  • 您的 CPU 是 Intel 的吗?您是否开启了超线程? (如果您没有明确将其关闭,则将其打开)
  • sleep()中的方法Thread抛出InterruptedException。您确定每个耗时的操作运行正好两秒吗?
  • 我看到有一个叫做“逻辑处理器”的东西,它的值是 12。所以 24 个元素的时间是 4 秒,但 25 个元素的时间是 6 秒。这一观察结果与逻辑处理器的数量 (12) 一致。我认为这可以解释但不确定。

标签: java multithreading java-stream


【解决方案1】:

您的 6 核 Intel CPU 已启用 HyperThreading。使用 HT,操作系统和应用程序将每个 CPU 内核视为 2 个独立的“逻辑内核”或“线程”(命名法各不相同)。这意味着ForkJoinPool 将使用 12 个线程而不是 6 个。

“逻辑核心”彼此之间共享一些资源,因此并行运行 12 个任务不会给您带来两倍于运行 6 个任务的吞吐量。但是只调用sleep() 的程序不会知道其中的区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 1970-01-01
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 2017-01-07
    相关资源
    最近更新 更多