我想全局替换Java并行流默认使用的公共线程池,例如,用于
IntStream.range(0,100).parallel().forEach(i -> {
doWork();
});
我知道可以通过将这样的指令提交给专用线程池来使用专用的ForkJoinPool(参见Custom thread pool in Java 8 parallel stream).这里的问题是
>是否有可能通过其他实现替换常见的ForkJoinPool(比如Executors.newFixedThreadPool(10)?
>是否可以通过某种全局设置来实现,例如,某些JVM属性?
备注:我之所以要更换F / J池,是因为它似乎有一个错误,使其无法用于嵌套并行循环.
例如:以下代码导致死锁:
// Outer loop
IntStream.range(0,24).parallel().forEach(i -> {
// (omitted:) do some heavy work here (consuming majority of time)
// Need to synchronize for a small "subtask" (e.g. updating a result)
synchronized(this) {
// Inner loop (does s.th. completely free of side-effects, i.e. expected to work)
IntStream.range(0,100).parallel().forEach(j -> {
// do work here
});
}
});
解决方法:
我认为这不是流API的使用方式.看起来你(错误地)使用它来执行并行任务执行(专注于任务,而不是数据),而不是进行并行流处理(专注于流中的数据).您的代码以某种方式违反了流的一些主要原则. (我正以’某种方式’写作,因为它并不是真的被禁止但是气馁):避免states and side effects.
除此之外(或者可能是因为副作用),你在外循环中使用了大量的同步,这是其他一切,但无害!
虽然文档中没有提到,但并行流在内部使用common ForkJoinPool.无论这是否缺乏文件,我们都必须接受这一事实. JavaDoc of ForkJoinTask指出:
It is possible to define and use ForkJoinTasks that may block, but doing do requires three further considerations: (1) Completion of few if any other tasks should be dependent on a task that blocks on external synchronization or I/O. Event-style async tasks that are never joined (for example, those subclassing CountedCompleter) often fall into this category. (2) To minimize resource impact, tasks should be small; ideally performing only the (possibly) blocking action. (3) Unless the ForkJoinPool.ManagedBlocker API is used, or the number of possibly blocked tasks is known to be less than the pool’s ForkJoinPool.getParallelism level, the pool cannot guarantee that enough threads will be available to ensure progress or good performance.
同样,您似乎使用流来替代简单的for循环和执行程序服务.
>如果您只想并行执行n个任务,请使用ExecutionService
>如果您有一个更复杂的示例,其中任务正在创建子任务,请考虑使用ForkJoinPool(使用ForkJoinTasks). (它确保了一定数量的线程而没有死锁的危险,因为等待其他任务完成的任务太多,因为等待任务不会阻塞其执行线程).
>如果要(并行)处理数据,请考虑使用流API.
>您无法“安装”自定义common pool.它是在私有静态代码内部创建的.
>但是你可以使用某些系统属性对公共池的并行性,线程工厂和异常处理程序产生影响(参见JavaDoc of ForkJoinPool)
不要混淆ExecutionService和ForkJoinPool.它们(通常)不是彼此的替代品!
标签:java,stream,multithreading,concurrency,parallel-processing
来源: https://codeday.me/bug/20190517/1119827.html