java 线程的公共区域_如何(全局)替换Java并行流的公共线程池后端?

本文讨论了如何全局替换Java并行流的默认公共线程池,特别是针对ForkJoinPool的问题。作者指出,虽然不能直接安装自定义的公共线程池,但可以通过JVM属性影响其配置。文章强调了并行流的正确使用方式,建议根据任务类型选择ExecutionService、ForkJoinPool或流API,并警告避免在并行流中引入副作用和过度同步,以防止死锁和性能问题。
摘要由CSDN通过智能技术生成

我想全局替换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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值