線程能夠經過實現Runnable接口,或者繼承Thread實現,可是這兩種方式在任務執行完成以後沒法獲取返回結果,因而就有了Callable接口,Future接口與FutureTask類配和來取得返回的結果。bash
Callable接口聲明瞭一個方法call(),同時這個方法返回值爲V,還能夠拋出異常。異步
Future用來獲取異步計算結果,提供如下方法聲明函數
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
複製代碼
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>
複製代碼
FutureTask類實現了RunnableFuture接口,FutureTask除了實現了Future接口外還實現了Runnable接口。FutureTask類是Future惟一實現類。spa
使用FutureTask時,根據FutureTask的構造函數能夠看到FutureTask既能夠接收Callable的實現類,也能夠接收Runnable的實現類。當你傳入的是Callable的實現類時,能夠獲取線程執行的結果;傳入Runnable的實現類時,因爲Runnable的實現沒有返回值,須要傳入一個你設置的線程完成標識,也就是result,而後當線程結束時會把你傳入的result原值返回。線程
咱們從ExecutorService接口中submit方法入手,看下AbstractExecutorService類對submit方法的具體實現。3d
使用submit方法提交任務時,都會經過newTaskFor方法轉換成FutureTask對象。code
因此ExecutorService接口中submit方法歸根結底仍是要把你傳入的對象封裝成FutureTask對象,並經過FutureTask類的內部實現來獲取結果的,返回的Future接口對象也要依賴於FutureTask實例化的,因此不管是直接傳入本身的Runnable、Callable實現類仍是構建FutureTask傳入,本質上都是經過FutureTask去實現,沒有什麼區別。cdn