这就是我遇到的问题:我有一些大型的对象序列(List<SomeClass>
),并希望对列表的所有元素执行一些操作并获得一个新的序列(List<SomeOtherClass>
)。
喜欢:
List<SomeOtherClass> list = new ArrayList<SomeOtherClass>();
for(SomeClass sc : originalList)
list.add(someOperation(sc));
由于操作someOperation
没有任何副作用,并且列表非常大,我希望这个映射操作可以并行化。
在Java中最好的方法是什么?
答案 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
到最后)。
这两个解决方案都有许多可用的教程和示例。