通过Java8并行流限制CPU使用率/ Java 8并行流使用高CPU

时间:2017-06-17 18:42:33

标签: java java-8 java-stream

我通过创建一个简单的循环并在数组中添加元素来测试java 8并行流api的性能。

我的性能比非并行性能大得多。

但是当我检查我的任务管理器时,我发现CPU使用率不受控制,在此期间它占用了我所有的CPU。 Check the CPU usage

这是我的示例代码,

    public static void withIfElse(boolean sorted) {

    int[] arr = new int[32768];
    Random rand = new Random();
    for(int i = 0;i < arr.length;i++)
        arr[i] = rand.nextInt(256);
    if(sorted)
        Arrays.parallelSort(arr);

    long nst = System.currentTimeMillis();
    long sum = 0;
    for(int j=0;j<100000;j++) {
        sum += Arrays.stream(arr).parallel().filter(m->m>=128).reduce((m,n)-> m+n).getAsInt();
    }

    System.out.printf("Time taken for boolean %b is %d ms. \n",sorted,(System.currentTimeMillis()-nst));

}

我能够实现近2倍到8倍的性能提升。

但是,

CPU使用率不受控制。有没有办法强制java只有2个核心?

我也尝试过设置

  

System.setProperty(&#34; java.util.concurrent.ForkJoinPool.common.parallelism&#34 ;,   &#34; 1&#34);

但CPU使用率仍然很高。

还建议使用并行流吗?因为在我的应用程序中假设我有10个用户线程,或者每个请求都是一个线程的Web应用程序,在这种情况下如果我在多个线程上启动并行流最终吃我所有的cpu,都会有这么多的上下文切换。

2 个答案:

答案 0 :(得分:2)

我的0.02 $:huge performance boost over non parallel one巨大的在这里可能有点太多了。这可能是有充分理由的 - 首先是你测试的方式。至关重要的是,有一个问题,超过500票,特别是对此:micro-benchmark。您可能认为您已经编写了良好的测试,但jvm可能会为您制定不同的计划。

对于中等数据,实际上顺序流可能比并行流更快。必须通过并行流完成更多工作。但如果没有实际测量,几乎不可能说出来;但这里有来自该领域最佳的推荐,如this

当你说你想要将java限制在一些核心时 - 简单的答案就是你不能;来自java代码。必须从OS完成,如果可行的话。通过java.util.concurrent.ForkJoinPool.common.parallelism启用的功能是限制线程,而不是核心。

单个线程可以分割为多个cpus - 它取决于操作系统本身。

答案 1 :(得分:1)

默认情况下,并行流在系统范围内的ForkJoinPool中运行,它为您机器上的每个核心提供一个线程。

如果您想更改此行为,可以在您选择的ForkJoinPool中运行并行流:

    ForkJoinPool fjp = new ForkJoinPool(2);
    ForkJoinTask<Long> sumFuture = fjp.submit(() -> {
        long sum = 0;
        for(int j=0;j<100000;j++) {
            sum += Arrays.stream(arr).parallel().filter(m->m>=128).reduce((m,n)-> m+n).getAsInt();
        }
        return sum;
    });