如何并行化列表的映射?

时间:2011-06-04 17:23:17

标签: java concurrency

这就是我遇到的问题:我有一些大型的对象序列(List<SomeClass>),并希望对列表的所有元素执行一些操作并获得一个新的序列(List<SomeOtherClass>)。

喜欢:

List<SomeOtherClass> list = new ArrayList<SomeOtherClass>();
for(SomeClass sc : originalList) 
  list.add(someOperation(sc));

由于操作someOperation没有任何副作用,并且列表非常大,我希望这个映射操作可以并行化。

在Java中最好的方法是什么?

5 个答案:

答案 0 :(得分:4)

可能的实现可以使用Executor框架(包括示例)。

答案 1 :(得分:1)

使用线程化并使用子列表对作品进行分区。

答案 2 :(得分:1)

拆分输入列表,并使用FutureTask任务,然后合并结果

答案 3 :(得分:0)

以下是我通常的做法:

// Somewhere define a static final int NUM_THREADS that is appropriate.

ExecutorService exec = Executors.newFixedThreadPool( NUM_THREADS );
// There are other options: look at what the Executors class has to offer.

List<SomeOtherClass> list = new ArrayList<SomeOtherClass>();

List<Future<SomeOtherClass>> list = new ArrayList<Future<SomeOtherClass>>();

for( SomeClass sc : originalList )
    futures.add( submit( new someOperation( sc ) ) );

for( Future<SomeOtherClass> future : futures )
    list.add( future.get() ); // Again, see the docs, you can also set a timeout.

exec.shutdown(); // Important. Otherwise the threads stay alive.
然后将

someOperation定义为可调用的

class someOperation extends Callable<SomeOtherClass> {

    private SomeClass input;

    public someOperation( SomeClass input ){
        this.input = input;
    }

    public SomeOtherClass call(){
        // Do your operation on 'input' here
    }
}

注意:我这里没有try - catch块,但您必须拥有一些。 shutdown应位于finally块中。我只是不记得是什么引发了什么ATM,你的IDE应该帮助你。

答案 4 :(得分:0)

Doug Lea的jsr166y包含了Fork / Join框架,它非常适合这种事情。它专为像这样的CPU密集型作业的并行分解而设计,并且非常高效。

使用它的最简单方法可能是使用新的Scala 2.9 parallel collections,因为它完全抽象了它的使用(在Scala中获取并行集合,只需添加.par到最后)。

这两个解决方案都有许多可用的教程和示例。