[英]How to parallelize a loop in Java
在以下代碼中,在HashSet的每個元素上調用一個本地方法。 如果返回一個特殊值,我們將停止循環。 否則,我們將每個返回值添加到新的HashSet中。
HashSet<Object> myHashSet=…;
HashSet<Object> mySecondHashSet=…;
for (Object s : myHashSet) {
Object value = my_method(s);
if(value==specialValue)
return value;
else
mySecondHashSet.add(value);
}
我想將這個過程並行化。 HashSet中的所有對象都沒有任何共同的對象(這是樹狀結構),因此我知道它們可以運行而沒有任何同步問題。 如何修改代碼,使my_method的每次調用開始一個新的過渡,並且如果一個線程的求值結果為特殊值,則所有線程都將暫停而不返回,並返回特殊值?
考慮到Java 8,這可能相對簡單,但它不會保留您的初始代碼語義:
萬一您需要擊中返回特殊值
if (myHashSet.parallelStream()
.map(x -> method(x))
.anyMatch(x -> x == specialValue)) {
return specialValue;
}
如果您需要保持轉換后的值直到滿足特殊值,您已經從@Elliot的注釋中得到了答案,同時需要提及的是語義與原始代碼不同,因為將不保留任何定序符。
雖然尚待檢查,但我希望可以優化以下內容,並在達到所需的特殊值時停止:
if (myHashSet.parallelStream()
.anyMatch(x -> method(x) == specialValue)) {
return specialValue;
}
我會分兩步這樣做:
為每個轉換啟動一個新線程太重了,並且會使您的機器癱瘓(除非您只有很少的元素,在這種情況下,並行化可能不值得付出努力。
為了避免使用my_method
兩次轉換值,您可以延遲進行轉換並記住結果:
private class Memoized {
private Object value;
private Object transformed;
private Function<Object, Object> transform;
public Memoized(Object value, Function<Object, Object> transform) {
this.value = value;
}
public Object getTransformed() {
if (transformed == null) {
transformed = transform.apply(value);
}
return transformed;
}
}
然后可以使用以下代碼:
Set<Memoized> memoizeds =
myHashSet.stream() // no need to go parallel here
.map(o -> new Memoized(o, this::my_method))
.collect(Collectors.toSet());
Optional<Memoized> matching = memoized.parallelStream()
.filter(m -> m.getTransformed().equals(specialValue))
.findAny();
if (matching.isPresent()) {
return matching.get().getTransformed();
}
Set<Object> allTransformed =
memoized.parallelStream()
.map(m -> m.getTransformed())
.collect(Collectors.toSet());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.