java 8 并行_Java 8并行流的性能陷阱

并行化流被分成多个块,每个块独立处理,结果在最后汇总。

CPU密集型代码如下:

private long countPrimes(int max) {

return range(1, max).parallel().filter(this::isPrime).count();

}

private boolean isPrime(long n) {

return n > 1 && rangeClosed(2, (long) sqrt(n)).noneMatch(divisor -> n % divisor == 0);

}

countPrimes 计算1到最大值之间的素数的数量。数字流由range方法创建,切换到并行模式,过滤掉非素数,剩余的计算总数。由于isPrime 方法极其无效且占用大量CPU,我们可以利用并行化并利用所有可用的CPU内核。

我们来看另一个例子:

private List getStockInfo(Stream symbols) {

return symbols.parallel()

.map(this::getStockInfo) //slow network operation.collect(toList());

}

输入是一个股票代码列表,我们必须调用慢速网络操作来获取有关股票的一些细节。在这里,我们不处理CPU密集型操作,但我们也可以利用并行化。并行执行多个网络请求是个好主意。同样,并行流的一个很好的任务,你同意吗?

如果您这样做,请再次查看上一个示例。有一个很大的错误。你看到了吗?问题是所有并行流都使用公共fork-join线程池。如果提交长时间运行的任务,则会有效地阻塞池中的所有线程。因此,您将阻塞使用并行流的所有其他任务。

想象一下servlet环境,当一个请求调用时getStockInfo() ,另一个请求调用  countPrimes()。即使每个都需要不同的资源,也会阻止另一个。更糟糕的是,你不能为并行流指定线程池; 整个类加载器必须使用相同的。

让我们在下面的例子中说明它:

private void run() throws InterruptedException {

ExecutorService es = Executors.newCachedThreadPool();

// Simulating multiple threads in the system// if one of them is executing a long-running task.// Some of the other threads/tasks are waiting// for it to finishes.execute(() -> countPrimes(MAX, 1000));//incorrect taskes.execute(() -> countPrimes(MAX, 0));

es.execute(() -> countPrimes(MAX, 0));

es.execute(() -> countPrimes(MAX, 0));

es.execute(() -> countPrimes(MAX, 0));

es.execute(() -> countPrimes(MAX, 0));

es.shutdown();

es.awaitTermination(60, TimeUnit.SECONDS);

}

private void countPrimes(int max, int delay) {

System.out.println( range(1, max).parallel() .filter(this::isPrime).peek(i -> sleep(delay)).count() );

}

在这里,我们模拟系统中的六个线程。所有这些都在执行CPU密集型任务,第一个被“暂停”,在它找到素数后就睡了一秒钟。这只是一个人为的例子; 你可以想象一个被卡住或执行阻塞操作的线程。

问题是:执行此代码时会发生什么?我们有六个任务; 其中一个将需要一整天才能完成,其余的应该更快完成。毫不奇怪,每次执行代码时,都会得到不同的结果。你想在生产系统中有这样的行为吗?一个杜塞的任务取消了应用程序的其余部分?我猜不会。

关于如何确保永远不会发生这样的事情,只有两种选择。第一个是确保提交到公共fork-join池的所有任务都不会卡,必须在合理的时间内完成。但这说起来容易做起来难,尤其是在复杂的应用程序中。

另一种选择是不使用并行流,并等到Oracle允许我们指定用于并行流的线程池。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值