Java 并发、流行为

标签 java concurrency java-8 java.util.concurrent

该类的方法getFirst()getSecond()是并发调用的。它是网络应用程序的一部分。

在没有并发的情况下也填充了内部映射。

public class MyClass {
    private Map<String, List<List<String>>> first;

    private Map<String, List<List<String>>> second;

    public MyClass() {
        first = new ConcurrentHashMap<>();
        second = new ConcurrentHashMap<>();
    }

    public Set<String> getFirst(String key, String token, int a, int b) {
        return get(first, key, token, a, b);
    }

    public Set<String> getSecond(String key, String token, int a, int b) {
        return get(second, key, token, a, b);
    }

    private Set<String> get(final Map<String, List<List<String>>> map, final String key, final String token,
        final int a, final int b) {
        Set<String> result = new TreeSet<>();
        map.get(key).stream().filter(i -> i.size() <= b && i.size() >= a).forEach(
            s -> result
                .addAll(s.stream().filter(p -> StringUtils.containsIgnoreCase(p, token)).collect(Collectors.toList())));
        return result;
    }
}

我用 ab -n 10000 -c 100(Apache 的实用程序)之类的东西对其进行了测试。我记录下来。我总是得到同样的一套。但是,如果我将 map.get(key).stream() 更改为 map.get(key).parallelStream() 并执行相同的步骤,我有时会得到不同的结果大小(总是更小)。

这是什么?

最佳答案

您正在并行流的 forEach 中使用 TreeSet.addAll()forEach 主体可以在不同线程中针对不同元素同时执行多次,并且 TreeSet不是线程安全的。要快速解决问题,您可以同步修改 result 或使用 forEachOrdered .然而,flatMap 会更干净、性能更好。您的流并在没有 forEach 的情况下立即收集它。试试这个版本:

return map.get(key).stream()
        .filter(i -> i.size() <= b && i.size() >= a)
        .flatMap(List::stream).filter(p -> StringUtils.containsIgnoreCase(p, token))
        .collect(Collectors.toCollection(TreeSet::new));

关于Java 并发、流行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30098262/

相关文章:

java - spring集成jms channel 设置并发消费者导致数据损坏

performance - 在 x86_64 汇编程序 (yasm) 中使用 POSIX 线程库需要更多的执行时间

java - ExecutorService "happens-before"中的 awaitTermination 是否在其后执行任何代码?

Java 8 在接口(interface)默认方法中使用枚举值

Java 流 : Organize a collection into a map and select smallest key

java Stream map和mapToObj的区别

java - jpa 遇到问题,当被告知忽略时看起来正在从缓存中读取

java - 从某个索引开始的最小数的索引

java - 从另一个类调用方法时遇到很多麻烦

java - 为 rabbitmq 配置 HAProxy