如何在Java中多线程处理计算密集型代码段?

时间:2010-11-25 00:32:39

标签: java multithreading

我有一个java程序,它的一部分是计算密集型的,就像这个

for i = 1 :512
   COMPUTE INTENSIVE SECTION
end

我希望将其拆分为多线程,在运行时加快速度。

COMPUTE INTENSIVE SECTION不是顺序的。这意味着首先运行i = 1或者i = 5拳头是相同的......

任何人都可以给我一个关于此的大指南。怎么做? 谢谢! 感恩节快乐!

5 个答案:

答案 0 :(得分:5)

您应该阅读Concurrency TrailJava Tutorial。特别是ExecutorsThread Pools应与您相关。

基本上,您通过the Executors class中的一个工厂方法创建一个线程池(Executor)并向其提交Runnable个实例:

for(int i = 0; i < 512; i++){
    executor.execute(new Runnable(){public void run(){
        // your heavy code goes here
    }});
}

答案 1 :(得分:3)

答案 2 :(得分:3)

听起来像线程池会很好。基本上,你掀起了N个不同线程的集合,然后循环请求它们。请求会阻塞,直到线程可用。

ThreadPool pool = Executors.newFixedThreadPool(10); // 10 threads in the pool
ArrayList<Callable> collectionOfCallables = new ArrayList<Callable>( );
for (...) {
  Callable callable = new Callable<Foo>() { public Foo call() { COMPUTE INTENSIVE SECTION } }
  collectionOfCallables.add(callable);
}

ArrayList<Future<Foo>> results = pool.invokeAll( collectionOfCallables );

pool.awaitTermination(5, TimeUnit.MINUTES ); // blocks till everything is done or 5 minutes have passed.

有了Future,你真的不需要等待终止。 get()来自未来的结果将阻塞,直到相应的线程完成(或取消)。

答案 3 :(得分:0)

类似于肖恩·帕特里克·弗洛伊德(Sean Patrick Floyd)的答案,但是对于lambda表达式来说,这一点不那么冗长:

ExecutorService es = Executors.newCachedThreadPool();
for(int i = 0; i < 512; i++){
    es.execute(() -> {
        // code goes here
    });
}

答案 4 :(得分:0)

如果您可以将强化操作拆分为递归较小的子任务,ForkJoinPool 非常适合您。

如果您的服务器使用8 core CPU运行,则可以将池大小设置为8

ForkJoinPool forkJoinPool = new ForkJoinPool(8); 

OR

您可以使用Executor Service FixedThreadPool将计算密集型任务移至Callable,如下所示

ExecutorService executorService = Executors.newFixedThreadPool(8);

Future future = executorService.submit(new Runnable() {
public void run() {
    System.out.println("Your compute intensive task");
}
});

future.get();  //returns null if the task has finished correctly.

ForkJoinPool有一个优势。空闲线程将从已提交Runnable/Callable任务的blokcingQueue中的忙线程中窃取作业。

Java 8在Executors中添加了一个新API:newWorkStealingPool

如果您需要等待所有任务的完成,请使用invokeAll()上的ExecutorService

使用Java 8查看Benjamin article有关高级并发API的信息