转自:http://hi.baidu.com/ecspell/blog/item/024e37fa87b0cf849e5146b0.html
FutureTask、 ExecutorService 相关知识,请看java,API
一个使用FutureTask简单的例子:
package com.spell.threads;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* 测试FutureTask的用法,如果不想分支线程阻塞主线程,又想取得分支线程的执行结果,就用FutureTask
*
* @author Administrator
*
*/
public class FutureTaskTest {
/**
* @param args
*/
public static void main(String[] args) {
CountNum cn = new CountNum(0);
//FutureTask<Integer> 这里的表示返回的是Integer
FutureTask<Integer> ft = new FutureTask<Integer>(cn);
Thread td = new Thread(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("取得分支线程执行的结果后,主线程可以继续处理其他事项");
}
}
class CountNum implements Callable {
private Integer sum;
public CountNum(Integer sum) {
this.sum = sum;
}
public Object call() throws Exception {
for (int i = 0; i < 100; i++) {
sum = sum + i;
}
// 休眠5秒钟,观察主线程行为,预期的结果是主线程会继续执行,到要取得FutureTask的结果是等待直至完成。
Thread.sleep(3000);
System.out.println("futureTask 执行完成" + System.currentTimeMillis());
return sum;
}
}
运行的结果是:
futureTask开始执行计算:1280114852250
main 主线程可以做些其他事情:1280114852250
futureTask 执行完成1280114855250
计算的结果是:4950
取得分支线程执行的结果后,主线程可以继续处理其他事项
如果有多个FutureTask要执行批量运算,从而充分的利用多核CPU,可以参考下面的代码:
package com.spell.threads;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
/**
* 测试多核时代,充分的利用CPU来运算数据,并且处理返回的结果,学习API专用
*
* @author Administrator
*
*/
public class FutureTaskAndExecutor {
/**
* @param args
*/
public static void main(String[] args) {
List<FutureTask<Integer>> list = new ArrayList<FutureTask<Integer>>();
// 创建线程池,线程池的大小和List.size没有啥必然的关系,一般的原则是<=list.size,多出来浪费不好
ExecutorService exec = Executors.newFixedThreadPool(5);
for (int i = 10; i < 20; i++) {
// 创建对象
FutureTask<Integer> ft = new FutureTask<Integer>(new GetSum(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);
}
}
/**
* 这个类很简单,就是统计下简单的加法(从1 到total)
*
* @author Administrator
*
*/
class GetSum implements Callable {
private Integer total;
private Integer sum = 0;
public GetSum(Integer total) {
this.total = total;
}
public Object call() throws Exception {
for (int i = 1; i < total + 1; i++) {
sum = sum + i;
}
System.out.println(Thread.currentThread().getName() + " sum:" + sum);
return sum;
}
}
运行的结果是:
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