java利用FutureTask、ExecutorService 在多核时代充分利用CPU运算
2010-07-26 11:28
FutureTask、ExecutorService 相关知识,请看java,API
一个使用FutureTask简单的例子:
futureTask开始执行计算:1280114852250
main 主线程可以做些其他事情:1280114852250
futureTask 执行完成1280114855250
计算的结果是:4950
取得分支线程执行的结果后,主线程可以继续处理其他事项
如果有多个FutureTask要执行批量运算,从而充分的利用多核CPU,可以参考下面的代码:
pool-1-thread-1 sum:120
pool-1-thread-1 sum:136
pool-1-thread-1 sum:153
pool-1-thread-1 sum:171
pool-1-thread-1 sum:190
pool-1-thread-2 sum:66
pool-1-thread-3 sum:78
pool-1-thread-4 sum:91
pool-1-thread-5 sum:105
多线程计算后的总结果是:1165
一个使用FutureTask简单的例子:
packagecom.spell.threads; importjava.util.concurrent.Callable; importjava.util.concurrent.ExecutionException; importjava.util.concurrent.FutureTask; publicclassFutureTaskTest { publicstaticvoidmain(String[] args) { CountNum cn =newCountNum(0); //FutureTask<Integer> 这里的表示返回的是Integer FutureTask<Integer> ft =newFutureTask<Integer>(cn); Thread td =newThread(ft); System.out.println("futureTask开始执行计算:" + System.currentTimeMillis()); td.start(); System.out.println("main 主线程可以做些其他事情:" + System.currentTimeMillis()); try{ // futureTask的get方法会阻塞,知道可以取得结果为止 Integer result = ft.get(); System.out.println("计算的结果是:" + result); }catch(InterruptedException e) { e.printStackTrace(); }catch(ExecutionException e) { e.printStackTrace(); } System.out.println("取得分支线程执行的结果后,主线程可以继续处理其他事项"); } } classCountNumimplementsCallable { privateInteger sum; publicCountNum(Integer sum) { this.sum = sum; } publicObject call()throwsException { for(inti = 0; i < 100; i++) { sum = sum + i; } // 休眠5秒钟,观察主线程行为,预期的结果是主线程会继续执行,到要取得FutureTask的结果是等待直至完成。 Thread.sleep(3000); System.out.println("futureTask 执行完成" + System.currentTimeMillis()); returnsum; } }运行的结果是:
futureTask开始执行计算:1280114852250
main 主线程可以做些其他事情:1280114852250
futureTask 执行完成1280114855250
计算的结果是:4950
取得分支线程执行的结果后,主线程可以继续处理其他事项
如果有多个FutureTask要执行批量运算,从而充分的利用多核CPU,可以参考下面的代码:
packagecom.spell.threads; importjava.util.ArrayList; importjava.util.List; importjava.util.concurrent.Callable; importjava.util.concurrent.ExecutionException; importjava.util.concurrent.ExecutorService; importjava.util.concurrent.Executors; importjava.util.concurrent.FutureTask; publicclassFutureTaskAndExecutor { publicstaticvoidmain(String[] args) { List<FutureTask<Integer>> list =newArrayList<FutureTask<Integer>>(); // 创建线程池,线程池的大小和List.size没有啥必然的关系,一般的原则是<=list.size,多出来浪费不好 ExecutorService exec = Executors.newFixedThreadPool(5); for(inti = 10; i < 20; i++) { // 创建对象 FutureTask<Integer> ft =newFutureTask<Integer>(newGetSum(i)); // 添加到list,方便后面取得结果 list.add(ft); // 一个个提交给线程池,当然也可以一次性的提交给线程池,exec.invokeAll(list); exec.submit(ft); } // 开始统计结果 Integer total = 0; for(FutureTask<Integer> tempFt : list) { try{ total = total + tempFt.get(); }catch(InterruptedException e) { e.printStackTrace(); }catch(ExecutionException e) { e.printStackTrace(); } } // 处理完毕,一定要记住关闭线程池,这个不能在统计之前关闭,因为如果线程多的话,执行中的可能被打断 exec.shutdown(); System.out.println("多线程计算后的总结果是:" + total); } } classGetSumimplementsCallable { privateInteger total; privateInteger sum = 0; publicGetSum(Integer total) { this.total = total; } publicObject call()throwsException { for(inti = 1; i < total + 1; i++) { sum = sum + i; } System.out.println(Thread.currentThread().getName() + " sum:" + sum); returnsum; } }运行的结果是:
pool-1-thread-1 sum:120
pool-1-thread-1 sum:136
pool-1-thread-1 sum:153
pool-1-thread-1 sum:171
pool-1-thread-1 sum:190
pool-1-thread-2 sum:66
pool-1-thread-3 sum:78
pool-1-thread-4 sum:91
pool-1-thread-5 sum:105
多线程计算后的总结果是:1165