Java 自定义ForkJoinPool中的嵌套ArrayList.ParallelStream()不均匀地使用线程

Java 自定义ForkJoinPool中的嵌套ArrayList.ParallelStream()不均匀地使用线程,java,multithreading,java-stream,visualvm,forkjoinpool,Java,Multithreading,Java Stream,Visualvm,Forkjoinpool,我想使用我的自定义ForkJoinPool与ArrayList.parallelStream()具有更多的并行性(默认情况下,它使用公共池) 我这样做: List<String> activities = new ArrayList<>(); for (int i = 0; i < 3000; i++) { activities.add(String.valueOf(i)); } ForkJoinPool pool = new ForkJoinPool(

我想使用我的自定义ForkJoinPool与ArrayList.parallelStream()具有更多的并行性(默认情况下,它使用公共池)

我这样做:

List<String> activities = new ArrayList<>();

for (int i = 0; i < 3000; i++) {
    activities.add(String.valueOf(i));
}

ForkJoinPool pool = new ForkJoinPool(10);
pool.submit(() ->
        activities.parallelStream()
        .map(s -> {
            try {
                System.out.println("Start task = " + s);
                Thread.sleep(100);
                System.out.println("End task = " + s);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return s;
        })
        .collect(toList())
).get();
List activities=new ArrayList();
对于(int i=0;i<3000;i++){
活动。添加(String.valueOf(i));
}
ForkJoinPool池=新的ForkJoinPool池(10);
pool.submit(()->
activities.parallelStream()
.map(s->{
试一试{
System.out.println(“启动任务=“+s”);
睡眠(100);
System.out.println(“结束任务=“+s”);
}捕捉(中断异常e){
e、 printStackTrace();
}
返回s;
})
.collect(toList())
).get();
当我观察in如何在VisualVM中工作时,我看到:

在某个点上,一些线程被停止,而其他线程完成其余的工作。当我查看垃圾场时,我看到线程处于驻车状态,它什么也不做

实验表明,如果你创建一个ForkJoinPool,其并行度参数是2的幂,那么一切都正常

List<String> activities = new ArrayList<>();

    for (int i = 0; i < 3000; i++) {
        activities.add(String.valueOf(i));
    }

    ForkJoinPool pool = new ForkJoinPool(16);
    pool.submit(() ->
            activities.parallelStream()
            .map(s -> {
                try {
                    System.out.println("Start task = " + s);
                    Thread.sleep(100);
                    System.out.println("End task = " + s);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return s;
            })
            .collect(toList())
    ).get();
List activities=new ArrayList();
对于(int i=0;i<3000;i++){
活动。添加(String.valueOf(i));
}
ForkJoinPool池=新的ForkJoinPool池(16);
pool.submit(()->
activities.parallelStream()
.map(s->{
试一试{
System.out.println(“启动任务=“+s”);
睡眠(100);
System.out.println(“结束任务=“+s”);
}捕捉(中断异常e){
e、 printStackTrace();
}
返回s;
})
.collect(toList())
).get();

它可以是小于64的二次幂中的任意一次(我不知道为什么,但它不超过ForkJoinPool的34个线程),但如果不是二次幂,我们会得到奇怪的行为


为什么会这样?如何使用它?

不要实例化您自己的ForkJoinPool,您应该为JoinPool.commonPool()调用工厂方法
,该方法应与可用的内核相适应

你能试试吗

无论如何,我认为您最好使用
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())