Java多线程系列--“JUC线程池”06之 Callable和Future
轉載自??Java多線程系列--“JUC線程池”06之 Callable和Future
Callable 和 Future 簡介
Callable 和 Future 是比較有趣的一對組合。當我們需要獲取線程的執行結果時,就需要用到它們。Callable用于產生結果,Future用于獲取結果。
1. Callable
Callable 是一個接口,它只包含一個call()方法。Callable是一個返回結果并且可能拋出異常的任務。
為了便于理解,我們可以將Callable比作一個Runnable接口,而Callable的call()方法則類似于Runnable的run()方法。
Callable的源碼如下:
public interface Callable<V> {V call() throws Exception; }說明:從中我們可以看出Callable支持泛型。
?
2. Future
Future 是一個接口。它用于表示異步計算的結果。提供了檢查計算是否完成的方法,以等待計算的完成,并獲取計算的結果。
Future的源碼如下:
public interface Future<V> {// 試圖取消對此任務的執行。boolean cancel(boolean mayInterruptIfRunning)// 如果在任務正常完成前將其取消,則返回 true。boolean isCancelled()// 如果任務已完成,則返回 true。boolean isDone()// 如有必要,等待計算完成,然后獲取其結果。V get() throws InterruptedException, ExecutionException;// 如有必要,最多等待為使計算完成所給定的時間之后,獲取其結果(如果結果可用)。V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException; }說明: Future用于表示異步計算的結果。它的實現類是FutureTask,在講解FutureTask之前,我們先看看Callable, Future, FutureTask它們之間的關系圖,如下:
說明:
(01) RunnableFuture是一個接口,它繼承了Runnable和Future這兩個接口。RunnableFuture的源碼如下:
(02) FutureTask實現了RunnableFuture接口。所以,我們也說它實現了Future接口。
?
示例和源碼分析(基于JDK1.7.0_40)
我們先通過一個示例看看Callable和Future的基本用法,然后再分析示例的實現原理。
import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutionException;class MyCallable implements Callable {@Override public Integer call() throws Exception {int sum = 0;// 執行任務for (int i=0; i<100; i++)sum += i;//return sum; return Integer.valueOf(sum);} }public class CallableTest1 {public static void main(String[] args) throws ExecutionException, InterruptedException{//創建一個線程池ExecutorService pool = Executors.newSingleThreadExecutor();//創建有返回值的任務Callable c1 = new MyCallable();//執行任務并獲取Future對象 Future f1 = pool.submit(c1);// 輸出結果System.out.println(f1.get()); //關閉線程池 pool.shutdown(); } }運行結果:
4950結果說明:
在主線程main中,通過newSingleThreadExecutor()新建一個線程池。接著創建Callable對象c1,然后再通過pool.submit(c1)將c1提交到線程池中進行處理,并且將返回的結果保存到Future對象f1中。然后,我們通過f1.get()獲取Callable中保存的結果;最后通過pool.shutdown()關閉線程池。
?
1. submit()
submit()在java/util/concurrent/AbstractExecutorService.java中實現,它的源碼如下:
public <T> Future<T> submit(Callable<T> task) {if (task == null) throw new NullPointerException();// 創建一個RunnableFuture對象RunnableFuture<T> ftask = newTaskFor(task);// 執行“任務ftask” execute(ftask);// 返回“ftask”return ftask; }說明:submit()通過newTaskFor(task)創建了RunnableFuture對象ftask。它的源碼如下:
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {return new FutureTask<T>(callable); }?
2. FutureTask的構造函數
FutureTask的構造函數如下:
public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();// callable是一個Callable對象this.callable = callable;// state記錄FutureTask的狀態this.state = NEW; // ensure visibility of callable }?
3. FutureTask的run()方法
我們繼續回到submit()的源碼中。
在newTaskFor()新建一個ftask對象之后,會通過execute(ftask)執行該任務。此時ftask被當作一個Runnable對象進行執行,最終會調用到它的run()方法;ftask的run()方法在java/util/concurrent/FutureTask.java中實現,源碼如下:
說明:run()中會執行Callable對象的call()方法,并且最終將結果保存到result中,并通過set(result)將result保存。
? ?之后調用FutureTask的get()方法,返回的就是通過set(result)保存的值。
?
更多內容
1.?Java多線程系列--“JUC線程池”02之 線程池原理(一)
2.?Java多線程系列--“JUC線程池”03之 線程池原理(二)
3.?Java多線程系列--“JUC線程池”04之 線程池原理(三)
4.?Java多線程系列--“JUC線程池”05之 線程池原理(四)
5.?Java多線程系列--“JUC線程池”01之 線程池架構
6.?Java多線程系列目錄(共xx篇)
總結
以上是生活随笔為你收集整理的Java多线程系列--“JUC线程池”06之 Callable和Future的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微软推出 Arm 咨询服务,帮助开发者开
- 下一篇: Java多线程干货系列(1):Java多