【问题标题】:java 8 parallel stream Issuejava 8并行流问题
【发布时间】:2018-07-31 16:44:08
【问题描述】:
    _logger.info("data size : "+saleData.size);

    saleData.parallelStream().forEach(data -> {
                SaleAggrData saleAggrData = new SaleAggrData() {
                    {
                        setCatId(data.getCatId());
                        setRevenue(RoundUpUtil.roundUpDouble(data.getRevenue()));
                        setMargin(RoundUpUtil.roundUpDouble(data.getMargin()));
                        setUnits(data.getUnits());
                        setMarginRate(ComputeUtil.marginRate(data.getRevenue(), data.getMargin()));
                        setOtd(ComputeUtil.OTD(data.getRevenue(), data.getUnits()));
                        setSaleDate(data.getSaleDate());
                        setDiscountDepth(ComputeUtil.discountDepth(data.getRegularPrice(), data.getRevenue()));
                        setTransactions(data.getTransactions());
                        setUpt(ComputeUtil.UPT(data.getUnits(), data.getTransactions()));
                    }
                };
                salesAggrData.addSaleAggrData(saleAggrData);
            });

代码的问题是,当我从 DB 获得响应时,并且在使用并行流进行迭代时,数据大小每次都不同,而在使用顺序流时它工作正常。

我不能使用连续的Stream,因为数据量很大并且需要时间。

任何线索都会有所帮助。

【问题讨论】:

  • 请注意——您使用的是 SaleAggrData 类的匿名子类,这是不必要的。这将对性能产生影响,因为必须在运行时加载一个额外的类。你最好使用SaleAggrData sad = new SaleAggrData(); sad.setCatId(...); sad.setRevenue(...); ...See performance impact measurements here.
  • 但是在流执行之前记录了数据大小......你在做什么?
  • salesAggrData 是线程安全集合吗?

标签: java parallel-processing java-8 parallel.foreach


【解决方案1】:

您正在添加与salesAggrData 并行的元素,我假设这是一些Collection。如果它不是线程安全的Collection,难怪你会得到不一致的结果。

你为什么不使用map()而不是forEach,然后将结果收集到一些Collection中?

List<SaleAggrData> salesAggrData =
    saleData.parallelStream()
            .map(data -> {
                    SaleAggrData saleAggrData = new SaleAggrData() {
                        {
                            setCatId(data.getCatId());
                            setRevenue(RoundUpUtil.roundUpDouble(data.getRevenue()));
                            setMargin(RoundUpUtil.roundUpDouble(data.getMargin()));
                            setUnits(data.getUnits());
                            setMarginRate(ComputeUtil.marginRate(data.getRevenue(), data.getMargin()));
                            setOtd(ComputeUtil.OTD(data.getRevenue(), data.getUnits()));
                            setSaleDate(data.getSaleDate());
                            setDiscountDepth(ComputeUtil.discountDepth(data.getRegularPrice(), data.getRevenue()));
                            setTransactions(data.getTransactions());
                            setUpt(ComputeUtil.UPT(data.getUnits(), data.getTransactions()));
                        }
                    };
                    return saleAggrData;
            })
            .collect(Collectors.toList());

顺便说一句,我可能会更改匿名类实例的创建,并使用命名类的构造函数来创建 SaleAggrData 实例。

【讨论】:

  • 而且我可能还是会使用顺序流,因为并行流可能会使事情变慢,而且大部分时间可能都花在执行查询和加载结果上,而不是转换它们。
  • @JBNizet 也许你是对的,尽管与顺序相比测试并行流的性能不会有任何影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-23
  • 1970-01-01
  • 2016-02-28
  • 2016-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多