【发布时间】:2015-05-07 10:22:12
【问题描述】:
同时调用该类的方法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() 并执行相同的步骤,我有时会得到不同的结果大小(总是更小)。
这是什么?
【问题讨论】:
-
尝试使用线程安全的集合来收集你的结果。
-
Set 的线程安全版本?
-
@SDmitry:为什么不呢?
Collections.newSetFromMap(new ConcurrentSkipListMap<String, Boolean>()) -
@SDmitry ConcurrentSkipListSet?
-
@OldCurmudgeon @TagirValeev 通过使用线程安全的 Collection 或 Map,您添加了另一个问题:由于同步锁定导致的争用。在高性能系统中,您希望不惜一切代价避免这种情况。最好在非线程安全的集合上使用线程安全的流操作。一些在
Collectors.*中定义并在stream.collect(...)中使用的收集器提供了提供线程安全而没有争用的智能方法。
标签: java concurrency java-8 java.util.concurrent