如何在Java中并行化循环

时间:2017-07-02 15:52:16

标签: java multithreading java-threads

在下面的代码中,在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的每个调用开始一个新的步骤,并且如果其中一个线程评估为特殊值,所有线程停止而不返回并返回特殊值?

2 个答案:

答案 0 :(得分:1)

考虑到java 8,这可能相对简单,但它不会保留您的初始代码语义:

如果您需要的只是在点击后返回特殊值

from concurrent.futures import TimeoutError
from pebble import ProcessPool

def function(n):
    return n

with ProcessPool() as pool:
    future = pool.schedule(function, args=[1], timeout=10)

    try:
        results = future.result()
    except TimeoutError as error:
        print("function took longer than %d seconds" % error.args[1])

如果你需要保持变换值直到你达到特殊值,你已经在评论中得到了@Elliot的答案,同时需要提到语义与你的原始代码不同,因为没有orderer会被保留。

虽然尚未检查,但我希望以下优化并停止一旦它达到想要的特殊价值:

$cart[$product->id] = $quantity;
var_dump($cart);
return redirect('catalogs')->withCookie(cookie()->forever('cart', serialize($cart)));

答案 1 :(得分:0)

我会两次通过:

  1. 查找是否有任何已转换的set元素与特殊值匹配;
  2. 将它们转换为Set。
  3. 为每次转换启动一个新线程太重了,会让你的机器瘫痪(除非你的元素很少,在这种情况下,并行化可能不值得付出努力。

    为避免使用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());