簡體   English   中英

Java並發,流行為

[英]Java concurrency, stream behavior

方法同時調用此類的getFirst()getSecond() 它是Web應用程序的一部分。

內部地圖也填充,沒有並發。

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 但是,如果沒有forEach那么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));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM