代码之家  ›  专栏  ›  技术社区  ›  Raghavan

由于RaceCondition,使用流迭代LinkedList正在更改结果列表

  •  1
  • Raghavan  · 技术社区  · 6 年前

    List<DesInfo> InfoList = new LinkedList<>();
    documentList.stream()
                .parallel()
                .forEach(document -> {
                    Info descriptiveInfo = objectFactory.createDescriptiveInfo();
                    List<Document> documents = new ArrayList<>();
                    documents.add(document);
                    descriptiveInfo.setHotelInfo(getHotelInfo(document.get(CODE), documents));
                    InfoList.add(Info);
                });
    

    如果每次运行此代码,我们都会看到为同一个documentList输入生成的InfoList大小不同。我浏览了一些论坛,他们提到LinkedList并不是线程安全的,而是任何线程安全的集合。但我的要求不允许我在LinkedList之外进行更改。我需要使用具有相同LinkedList的并行流功能。

    谢谢, 拉加万

    2 回复  |  直到 6 年前
        1
  •  2
  •   Lino    6 年前

    而不是使用 forEach 使用 Collector map() 操作:

    List<HotelDescriptiveInfo> hotelDescriptiveInfoList = documentList.parallelStream()
        .map(document -> {
            HotelDescriptiveInfo descriptiveInfo = objectFactory.createHotelDescriptiveInfo();
            List<Document> documents = new ArrayList<>();
            documents.add(document);
            descriptiveInfo.setHotelInfo(getHotelInfo(document.get(HOTEL_CODE), documents));
            return descriptiveInfo;
        })
        .collect(Collectors.toCollection(LinkedList::new));
    

    这个 Stream api将负责处理,不允许出现竞争条件。

        2
  •  2
  •   ETO    6 年前

    使用 collect 而不是改变集合的状态。

    private DesInfo documentToDesInfo(Document document){
        DesInfo info = objectFactory.createDescriptiveInfo();
        List<Document> documents = new ArrayList<>();
        documents.add(document);
        info.setHotelInfo(getHotelInfo(document.get(CODE), documents));
        return info;
    }
    

    然后在你的管道中使用它:

    List<DesInfo> infoList = documentList.parallelStream()
                                         .map(this::documentToDesInfo)
                                         .collect(toCollection(LinkedList::new));