首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ForkJoinPool性能Java8 vs 11

ForkJoinPool性能Java8 vs 11
EN

Stack Overflow用户
提问于 2019-01-08 03:41:16
回答 1查看 4.5K关注 0票数 4

请考虑以下代码:

代码语言:javascript
复制
package com.sarvagya;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;

public class Streamer {
    private static final int LOOP_COUNT  = 2000;
    public static void main(String[] args){
        try{
            for(int i = 0; i < LOOP_COUNT; ++i){
                poolRunner();
                System.out.println("done loop " + i);
                try{
                    Thread.sleep(50L);
                }
                catch (Exception e){
                    System.out.println(e);
                }
            }
        }
        catch (ExecutionException | InterruptedException e){
            System.out.println(e);
        }

        // Add a delay outside the loop to make sure all daemon threads are cleared before main exits.
        try{
            Thread.sleep(10 * 60 * 1000L);
        }
        catch (Exception e){
            System.out.println(e);
        }
    }

    /**
     * poolRunner method.
     * Assume I don't have any control over this method e.g. done by some library.
     * @throws InterruptedException
     * @throws ExecutionException
     */
    private static void poolRunner() throws InterruptedException, ExecutionException {
        ForkJoinPool pool = new ForkJoinPool();
        pool.submit(() ->{
            List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10, 11,12,14,15,16);
            List<Integer> collect = numbers.stream()
                    .parallel()
                    .filter(xx -> xx > 5)
                    .collect(Collectors.toList());
            System.out.println(collect);
        }).get();
    }
}

在上面的代码中,poolRunner方法创建了一个ForkJoinPool并向它提交了一些任务。当使用Java 8并将LOOP_COUNT保持为2000时,我们可以看到所创建的最大线程大约为3600个,如下所示

图:特征分析

图:线程信息。

经过一段时间后,所有这些线程都会下降到几乎10个。但是,在OpenJDK 11中,保持相同的LOOP_COUNT将产生以下错误:

代码语言:javascript
复制
[28.822s][warning][os,thread] Failed to start thread - pthread_create failed (EAGAIN) for attributes: stacksize: 1024k, guardsize: 4k, detached.
[28.822s][warning][os,thread] Failed to start thread - pthread_create failed (EAGAIN) for attributes: stacksize: 1024k, guardsize: 4k, detached.
[28.822s][warning][os,thread] Failed to start thread - pthread_create failed (EAGAIN) for attributes: stacksize: 1024k, guardsize: 4k, detached.
Exception in thread "ForkJoinPool-509-worker-5" java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached
    at java.base/java.lang.Thread.start0(Native Method)
    at java.base/java.lang.Thread.start(Thread.java:803)
    at java.base/java.util.concurrent.ForkJoinPool.createWorker(ForkJoinPool.java:1329)
    at java.base/java.util.concurrent.ForkJoinPool.tryAddWorker(ForkJoinPool.java:1352)
    at java.base/java.util.concurrent.ForkJoinPool.signalWork(ForkJoinPool.java:1476)
    at java.base/java.util.concurrent.ForkJoinPool.deregisterWorker(ForkJoinPool.java:1458)
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187)

它很快就达到了最大的线程极限。将LOOP_COUNT保持到500,工作正常,但是,这些线程被清除得非常慢,并且达到了大约500个线程的平台。见以下图片:

图: OpenJDK 11中的线程信息

图: OpenJDK 11中的分析

将线程存储在JDK 8中,但是WAIT在JDK 11中。在Java 11中也应该减少守护进程线程的数量,但是它的速度很慢,不能像预期的那样工作。此外,假设我无法控制poolRunner方法。考虑到这个方法是由一些外部库提供的。

这是OpenJDK 11的问题,还是代码中的错误。谢谢。

EN

回答 1

Stack Overflow用户

发布于 2019-01-08 04:13:01

你做得不对。

在上面的代码中,我创建了一个ForkJoinPool并向它提交了一些任务。

实际上,您正在创建2000个ForkJoinPool实例.

不需要这样做,您应该创建一个具有大量并行性(即线程数)的单个ForkJoinPool,这些并行性适合于手头的任务。

创建大量线程(即数千个线程)是一个非常糟糕的主意。即使不触发OOME,也会消耗大量堆栈和堆内存,并在调度程序和垃圾收集器上放置大量负载.没有真正的好处。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54084915

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档