Java中是否存在与Scala中的并行集合相近的内容?

时间:2011-07-25 18:10:08

标签: java scala parallel-processing

使用Java实现并行计算(例如在多核处理器上)的最简单方法是什么。 I.E. java等效于此Scala代码

val list = aLargeList
list.par.map(_*2)

this library,但似乎势不可挡。

4 个答案:

答案 0 :(得分:7)

http://gee.cs.oswego.edu/dl/jsr166/dist/extra166ydocs/

不要放弃这么快,快活! ))

From the javadocs(改变映射到你的f)基本问题实际上就是这样:

ParallelLongArray a = ... // you provide
a.replaceWithMapping (new LongOp() { public long op(long a){return a*2L;}};);

就是这个,对吧?

val list = aLargeList
list.par.map(_*2)

&安培;如果你愿意不那么简洁,上面的内容可以是一个相当干净和清晰的3衬里(当然,如果你重用函数,那么它与Scala - 内联函数完全相同。):

ParallelLongArray a = ... // you provide
LongOp f = new LongOp() { public long op(long a){return a*2L;}};
a.replaceWithMapping (f);

[上面编辑以显示简明的完整形式ala OP的Scala变体]

在这里它是最大的详细形式,我们从头开始演示:

import java.util.Random;
import jsr166y.ForkJoinPool;
import extra166y.Ops.LongGenerator;
import extra166y.Ops.LongOp;
import extra166y.ParallelLongArray;

public class ListParUnaryFunc {
    public static void main(String[] args) {

        int n = Integer.parseInt(args[0]);
        // create a parallel long array 
        // with random long values
        ParallelLongArray a =  ParallelLongArray.create(n-1, new ForkJoinPool());
        a.replaceWithGeneratedValue(generator);

        // use it: apply unaryLongFuncOp in parallel 
        //         to all values in array
        a.replaceWithMapping(unaryLongFuncOp);

        // examine it
        for(Long v : a.asList()){
            System.out.format("%d\n", v);
        }
    }

    static final Random rand = new Random(System.nanoTime());
    static LongGenerator generator = new LongGenerator() {
        @Override final
        public long op() { return rand.nextLong(); }
    };

    static LongOp unaryLongFuncOp = new LongOp() {
        @Override final public long op(long a) { return a * 2L; }
    };
}

最终编辑和备注:

另请注意一个简单的类,例如以下(您可以在项目中重复使用):

/**
 * The very basic form w/ TODOs on checks, concurrency issues, init, etc.
 */
final public static class ParArray {
    private ParallelLongArray parr;
    private final long[] arr;
    public ParArray (long[] arr){
        this.arr = arr;
    }
    public final ParArray par() {
        if(parr == null)
            parr = ParallelLongArray.createFromCopy(arr, new ForkJoinPool()) ;
        return this;
    }
    public final ParallelLongArray map(LongOp op) {
        return parr.replaceWithMapping(op);
    }
    public final long[] values() { return parr.getArray(); }
}

之类的东西可以让你编写更流畅的Java代码(如果简洁对你很重要):

long[] arr = ... // you provide
LongOp f = ... // you provide

ParArray list = new ParArray(arr);
list.par().map(f);

上述方法当然可以推动,使其更加清洁。

答案 1 :(得分:1)

在一台机器上执行此操作非常简单,但并不像Scala那样容易。您发布的库已经是Java 5及更高版本的一部分了。可能最简单的事情是ExecutorService。这表示可以在任何处理器上运行的一系列线程。你发送任务,那些东西会返回结果。

http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html

http://www.fromdev.com/2009/06/how-can-i-leverage-javautilconcurrent.html

我建议使用ExecutorService.invokeAll(),它将返回Futures列表。然后你可以查看它们是否完成。

如果您正在使用Java7,那么您可以使用fork / join框架,这可能会为您节省一些工作。通过所有这些,您可以构建与Scala并行数组非常相似的东西,因此使用它非常简洁。

答案 2 :(得分:0)

使用线程,Java没有内置的这种东西。

答案 3 :(得分:0)

Java 8中将有一个等价物:http://www.infoq.com/articles/java-8-vs-scala