Thread類和Runnable接口和Java記憶體管理模型使得多線程程式設計簡單直接。但是Thread類和Runnable接口都不允許聲明檢查型異常,也不能定義傳回值。
Callable接口和Future接口的引入以及它們對線程池的支援優雅的解決了這兩個問題。
Callable接口類似于Runnable接口,Callable接口被線程執行後,可以傳回值,這個傳回值可以被Future拿到,也就是說,Future可以拿到異步執行任務的傳回值。Future取得的結果類型和Callable傳回的結果類型必須一緻,這是通過泛型來實作的。
1、Callable要采用ExecutorService的submit方法送出,傳回的future對象可以取消任務
代碼:
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
// submit是送出以便傳回結果
Future<String> future = threadPool.submit(new Callable<String>() {
public String call() throws Exception {
Thread.sleep(2000);
return "hello";
};
});
System.out.println("等待結果");
try {
System.out.println("拿到結果:" + future.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
結果:

Executor使我們無需顯示的去管理線程的生命周期。
2、執行多個帶傳回值的任務,并取得多個傳回值
//方式2 CompletionService用于送出一組Callable任務,其take方法傳回已完成的一個Callable任務對應的Future對象
//好比我同時種了幾塊地的麥子,然後就等待收割。收割時,則是那塊先成熟了,則先去收割哪塊麥子。
ExecutorService threadPool2 = Executors.newFixedThreadPool(10);
CompletionService<Integer> compeletionService = new ExecutorCompletionService<Integer>(
threadPool2);
for (int i = 0; i <= 10; i++) {
final int seq = i;
compeletionService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(new Random().nextInt(5000));
return seq;
}
});
}
for (int i = 0; i < 10; i++) {
try {
//産生線程,傳回結果再把結果拿回來
System.out.println(compeletionService.take().get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
結果:
3、了解Callable接口以及Future接口
Callable接口與Runnable接口的差別
1)Callable定義的方法時call,而Runnable定義的方法是run
2)Callable的call方法可以由傳回值,而Runnable的run方法不能有傳回值
3)Callable的call方法可以抛異常,而Runnable的run方法不能抛異常
Future表示一步計算的結果,它提供了檢查計算是否完成的方法,以等待計算的完成,并檢索計算的結果。Future的calcel方法可以取消任務的執行,它有一布爾參數,參數為true表示立即終端任務的執行,參數為false表示允許正在運作的任務運作完成。Future的get方法等待計算完成,擷取計算結果。