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

时间:2018-03-02 11:22:27

标签: 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(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();

当我观察VisualVM的工作方式时,我看到: VisualVM with parallelism 10

在某些时候某些线程被停放,而其他线程完成其余的工作。当我看着转储时,我看到没有做任何事情的线程处于停车状态。

实验上,据透露,如果你创建一个具有并行性参数的ForkJoinPool,那么一切都是正确的......

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();

VisualVM with parallelism 8

它可以是小于64的任何两个幂(我不知道为什么但它不超过ForkJoinPool的34个线程),但如果它不是2的幂,我们得到奇怪的行为。

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

1 个答案:

答案 0 :(得分:0)

您应该调整工厂方法ForJoinPool.commonPool(),而不是实例化您自己的ForkJoinPool,而工厂方法{/ 1}}应该与您的可用内核进行匹配。

你能试一试。

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