[英]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.