简体   繁体   English

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

[英]Nested ArrayList.ParallelStream() in custom ForkJoinPool uses threads unevenly

I want to use my custom ForkJoinPool to have more parallelism with ArrayList.parallelStream() (by default it uses common pool). 我想使用自定义的ForkJoinPool与ArrayList.parallelStream()具有更多的并行性(默认情况下,它使用公共池)。

I do this: 我这样做:

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

and when I observe how in works in VisualVM, I see: VisualVM with parallelism 10 当我观察VisualVM的工作原理时,我看到: 具有并行性的VisualVM 10

At some point some threads are parked and the other threads do the rest of the work. 在某些时候,某些线程被驻留,而其他线程则完成其余工作。 When I looked at the dump, I saw that threads, which does nothing, was in parking state. 当我查看转储时,我发现不执行任何操作的线程处于停车状态。

Experimentally, it was revealed that if you create a ForkJoinPool with parallelism parameter what is a power of two, everything is OK... 从实验上发现,如果您创建一个具有并行度参数的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();

VisualVM with parallelism 8 具有并行性的VisualVM 8

It can be any of powers of two less than 64 (I don't know why but it's not more than 34 threads of the ForkJoinPool), but if it is not power of two, we get the strange behaviour. 它可以是小于64的2的幂(我不知道为什么,但是它不超过ForkJoinPool的34个线程),但是如果不是2的幂,我们会得到奇怪的行为。

Why it happens? 为什么会发生? How to work with it? 如何使用它?

Instead of instanciating your own ForkJoinPool, you should invoque the factory method ForJoinPool.commonPool() which should be adapted with your available cores. 而不是实例化您自己的ForkJoinPool,您应该调用工厂方法ForJoinPool.commonPool() ,该方法应与可用的内核适配。

Can you give a try. 你可以试一下。

Anyway, I think you'd better have to use Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()) instead. 无论如何,我认为您最好使用Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM