我有一个java程序,它的一部分是计算密集型的,就像这个
for i = 1 :512
COMPUTE INTENSIVE SECTION
end
我希望将其拆分为多线程,在运行时加快速度。
COMPUTE INTENSIVE SECTION不是顺序的。这意味着首先运行i = 1或者i = 5拳头是相同的......
任何人都可以给我一个关于此的大指南。怎么做? 谢谢! 感恩节快乐!
答案 0 :(得分:5)
您应该阅读Concurrency Trail的Java Tutorial。特别是Executors和Thread 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)
查看任何Java多线程教程,可以是官方的:
或其他一些人,例如:
答案 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的信息