【问题标题】:Right way to combine group of collections组合集合组的正确方法
【发布时间】:2019-11-02 18:31:40
【问题描述】:

我已经做了一些代码来合并包含对[String,Integer],示例的并行集合组

线程 1 [汽车,1][熊,1][汽车,1]

线程 2 [河流,1][汽车,1][河流,1]

结果应该是每个唯一键对的集合(按字母顺序排序)

[熊,1]

[汽车,1][汽车,1][汽车,1]

[河流,1][河流,1][河流,1]

我的解决方案如下所示,但有时我没有得到预期的结果或 ConcurrentModificationException 从包含结果集合的列表中抛出

List<Collection<Pair<String, Integer>>> combiningResult = new ArrayList<>();

private void startMappingPhase() throws Exception {
    SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss.SSS");
    Invoker invoker = new Invoker(mappingClsPath, "Mapping", "mapper");
    List<Callable<Integer>> tasks = new ArrayList<>();
    for (String line : fileLines) {
        tasks.add(() -> {
            try {
                combine((Collection<Pair<String, Integer>>) invoker.invoke(line));
            } catch (Exception e) {
                e.printStackTrace();
                executor.shutdownNow();
                errorOccurred = true;
                return 0;
            }
            return 1;
        });

        if (errorOccurred)
            Utils.showFatalError("Some error occurred, See log for more detalis");
    }
    long start = System.nanoTime();
    System.out.println(tasks.size() + " Tasks");
    System.out.println("Started at " + formatter.format(new Date()) + "\n");


    executor.invokeAll(tasks);

    long elapsedTime = System.nanoTime() - start;

    partitioningResult.forEach(c -> {
        System.out.println(c.size() + "\n" + c);
    });


    System.out.print("\nFinished in " + (elapsedTime / 1_000_000_000.0) + " milliseconds\n");
}

private void partition(Collection<Pair<String, Integer>> pairs) {

    Set<Pair<String, Integer>> uniquePairs = new LinkedHashSet<>(pairs);

    for (Pair<String, Integer> uniquePair : uniquePairs) {

        int pFrequencyCount = Collections.frequency(pairs, uniquePair);

        Optional<Collection<Pair<String, Integer>>> collResult = combiningResult.stream().filter(c -> c.contains(uniquePair)).findAny();
        if (collResult.isPresent()) {
            collResult.ifPresent(c -> {
                for (int i = 0; i < pFrequencyCount; i++)
                    c.add(uniquePair);
            });
        } else {
            Collection<Pair<String, Integer>> newColl = new ArrayList<>();
            for (int i = 0; i < pFrequencyCount; i++)
                newColl.add(uniquePair);
            combiningResult.add(newColl);
        }

    }
}

我试过 CopyOnWriteList 坚持 ArrayList 但有时它会得到不完整的结果,比如

[Car,1][Car,1] 坚持三个条目,我的问题

有没有办法实现我正在尝试做的事情而不会得到 ConcurrentModificationException 和不完整的结果?

An example image

【问题讨论】:

    标签: java multithreading list collections java-stream


    【解决方案1】:

    如果您尝试从多个线程修改单个集合,则需要添加同步块或使用支持并发的 JDK 类之一。这些通常会比同步块执行得更好。

    https://docs.oracle.com/javase/tutorial/essential/concurrency/collections.html

    【讨论】:

      猜你喜欢
      • 2018-02-10
      • 1970-01-01
      • 2011-12-22
      • 2021-10-26
      • 2012-08-06
      • 1970-01-01
      • 1970-01-01
      • 2020-12-27
      • 2012-01-24
      相关资源
      最近更新 更多