Callable、Future和FutureTask
- 通常大家都知道建立線程的方式主要是繼承Thread和實作Runable接口,下面為大家介紹第三種方式,實作Callable接口。Callable可以在ExecutorService的線程池中跑,并有傳回結果;也可以通過傳回的FutureTask通過new Thread的方法啟動。兩種方法通過Future的擷取執行狀态(Future 本身也是一種設計模式,它是用來取得異步任務的結果)。
結構圖

上圖可以發現,FutureTask類是Future 的一個實作,并實作了Runnable。由FutureTask的構造方法,通過futureTask的run方法,啟動callable的call方法。如果在主線程中需要執行比較耗時的操作時,但又不想阻塞主線程時,可以把這些作業交給Future對象在背景完成,當主線程将來需要時,就可以通過Future對象獲得背景作業的計算結果或者執行狀态。
常用的方法介紹:
- isDone,結束,正常還是異常結束,或者自己取消,傳回true;
- isCancelled 任務完成前被取消,傳回true;
-
cancel(boolean):
1、任務還沒開始,傳回false
2、任務已經啟動,cancel(true),中斷正在運作的任務,中斷成功,傳回true,cancel(false),不會去中斷已經運作的任務
3、任務已經結束,傳回false
執行個體
public class UseFuture {
/*實作Callable接口,允許有傳回值*/
private static class UseCallable implements Callable<Integer>{
private int sum;
@Override
public Integer call() throws Exception {
System.out.println("Callable子線程開始計算");
Thread.sleep(2000);
for(int i=0;i<5000;i++) {
sum = sum+i;
}
System.out.println("Callable子線程計算完成,結果="+sum);
return sum;
}
}
public static void main(String[] args)
throws InterruptedException, ExecutionException {
UseCallable useCallable = new UseCallable();
FutureTask<Integer> futureTask = new FutureTask<Integer>(useCallable);
new Thread(futureTask).start();
Random r = new Random();
SleepTools.second(1);
if(r.nextBoolean()) {//随機決定是獲得結果還是終止任務
System.out.println("Get UseCallable result = "+futureTask.get());
}else {
System.out.println("中斷計算");
futureTask.cancel(true);
}
}
}
上面隻介紹了通過newThread()的方式啟動Callable,也可以通過線程池ExecutorService來啟動線程。想知道底層實作就多看看源碼學習,這裡就不過多說明