Java 并发、流行为
Java concurrency, stream behavior
此 class 的方法 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
is not thread-safe. To fix the problem quickly you can either synchronize modification of result
or use forEachOrdered
. However it would be cleaner and more performant to 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));
此 class 的方法 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
is not thread-safe. To fix the problem quickly you can either synchronize modification of result
or use forEachOrdered
. However it would be cleaner and more performant to 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));