出自[Java多線程編程中Future模式的詳解](http://blog.csdn.net/ghuil/article/details/41048017)
[TOC=1,2]
[Java](http://lib.csdn.net/base/javase "Java SE知識庫")多線程編程中,常用的多線程設計模式包括:Future模式、Master-Worker模式、Guarded Suspeionsion模式、不變模式和生產者-消費者模式等。這篇文章主要講述Future模式,關于其他多線程設計模式的地址如下:
關于其他多線程設計模式的地址如下:
關于Master-Worker模式的詳解:[?Java多線程編程中Master-Worker模式的詳解](http://blog.csdn.net/ghuil/article/details/41048005)
關于Guarded Suspeionsion模式的詳解:[?Java多線程編程中Guarded Suspeionsion模式的詳解](http://blog.csdn.net/ghuil/article/details/41047999)
關于不變模式的詳解:[?Java多線程編程中不變模式的詳解](http://blog.csdn.net/ghuil/article/details/41047979)
關于生產者-消費者模式的詳解:[生產者-消費者模式Java詳解](http://blog.csdn.net/ghuil/article/details/41044257)
# 1\. Future模式核心思想
Future模式的核心在于:去除了主函數的等待時間,并使得原本需要等待的時間段可以用于處理其他業務邏輯(根據《Java程序性能優化》)。
Future模式有點類似于商品訂單。在網上購物時,提交訂單后,在收貨的這段時間里無需一直在家里等候,可以先干別的事情。類推到程序設計中時,當提交請求時,期望得到答復時,如果這個答復可能很慢。傳統的時一直等待到這個答復收到時再去做別的事情,但如果利用Future設計模式就無需等待答復的到來,在等待答復的過程中可以干其他事情。
例如如下的請求調用過程時序圖。當call請求發出時,需要很長的時間才能返回。左邊的圖需要一直等待,等返回數據后才能繼續其他操作;而右邊的Future模式的圖中客戶端則無需等到可以做其他的事情。服務器段接收到請求后立即返回結果給客戶端,這個結果并不是真實的結果(是虛擬的結果),也就是先獲得一個假數據,然后執行其他操作。

# 2\. Future模式Java實現
**Client的實現**
Client主要完成的功能包括:1\. 返回一個FutureData;2.開啟一個線程用于構造RealData。**
**
**[cpp]**?[view plain](http://blog.csdn.net/ghuil/article/details/41048017# "view plain")?[copy](http://blog.csdn.net/ghuil/article/details/41048017# "copy")
1. public?class?Client?{??
2. ????public?Data?request(final?String?string)?{??
3. ????????final?FutureData?futureData?=?new?FutureData();??
4. ??????????
5. ????????new?Thread(new?Runnable()?{??
6. ????????????@Override??
7. ????????????public?void?run()?{??
8. ????????????????//RealData的構建很慢,所以放在單獨的線程中運行??
9. ????????????????RealData?realData?=?new?RealData(string);??
10. ????????????????futureData.setRealData(realData);??
11. ????????????}??
12. ????????}).start();??
13. ??????????
14. ????????return?futureData;?//先直接返回FutureData??
15. ????}??
16. }??
**Data的實現**
無論是FutureData還是RealData都實現該接口。**
**
**[java]**?[view plain](http://blog.csdn.net/ghuil/article/details/41048017# "view plain")?[copy](http://blog.csdn.net/ghuil/article/details/41048017# "copy")
1. public?interface?Data?{??
2. ????String?getResult()?throws?InterruptedException;??
3. }??
**FutureData的實現**
FutureData是Future模式的關鍵,它實際上是真實數據RealData的代理,封裝了獲取RealData的等待過程。
**[java]**?[view plain](http://blog.csdn.net/ghuil/article/details/41048017# "view plain")?[copy](http://blog.csdn.net/ghuil/article/details/41048017# "copy")
1. //FutureData是Future模式的關鍵,它實際上是真實數據RealData的代理,封裝了獲取RealData的等待過程??
2. public?class?FutureData?implements?Data?{??
3. ????RealData?realData?=?null;?//FutureData是RealData的封裝??
4. ????boolean?isReady?=?false;??//是否已經準備好??
5. ??????
6. ????public?synchronized?void?setRealData(RealData?realData)?{??
7. ????????if(isReady)??
8. ????????????return;??
9. ????????this.realData?=?realData;??
10. ????????isReady?=?true;??
11. ????????notifyAll();?//RealData已經被注入到FutureData中了,通知getResult()方法??
12. ????}??
13. ??
14. ????@Override??
15. ????public?synchronized?String?getResult()?throws?InterruptedException?{??
16. ????????if(!isReady)?{??
17. ????????????wait();?//一直等到RealData注入到FutureData中??
18. ????????}??
19. ????????return?realData.getResult();???
20. ????}??
21. }??
**RealData的實現**
RealData是最終需要使用的數據,它的構造函數很慢。
**[java]**?[view plain](http://blog.csdn.net/ghuil/article/details/41048017# "view plain")?[copy](http://blog.csdn.net/ghuil/article/details/41048017# "copy")
1. public?class?RealData?implements?Data?{??
2. ????protected?String?data;??
3. ??
4. ????public?RealData(String?data)?{??
5. ????????//利用sleep方法來表示RealData構造過程是非常緩慢的??
6. ????????try?{??
7. ????????????Thread.sleep(1000);??
8. ????????}?catch?(InterruptedException?e)?{??
9. ????????????e.printStackTrace();??
10. ????????}??
11. ????????this.data?=?data;??
12. ????}??
13. ??
14. ????@Override??
15. ????public?String?getResult()?{??
16. ????????return?data;??
17. ????}??
18. }??
**測試運行**
主函數主要負責調用Client發起請求,并使用返回的數據。
**[java]**?[view plain](http://blog.csdn.net/ghuil/article/details/41048017# "view plain")?[copy](http://blog.csdn.net/ghuil/article/details/41048017# "copy")
1. public?class?Application?{??
2. ????public?static?void?main(String[]?args)?throws?InterruptedException?{??
3. ????????Client?client?=?new?Client();??
4. ????????//這里會立即返回,因為獲取的是FutureData,而非RealData??
5. ????????Data?data?=?client.request("name");??
6. ????????//這里可以用一個sleep代替對其他業務邏輯的處理??
7. ????????//在處理這些業務邏輯過程中,RealData也正在創建,從而充分了利用等待時間??
8. ????????Thread.sleep(2000);??
9. ????????//使用真實數據??
10. ????????System.out.println("數據="+data.getResult());??
11. ????}??
12. }??
# 3\. Future模式的JDK內置實現
由于Future是非常常用的多線程設計模式,因此在JDK中內置了Future模式的實現。這些類在java.util.concurrent包里面。其中最為重要的是FutureTask類,它實現了Runnable接口,作為單獨的線程運行。在其run()方法中,通過Sync內部類調用Callable接口,并維護Callable接口的返回對象。當使用FutureTask.get()方法時,將返回Callable接口的返回對象。同樣,針對上述的實例,如果使用JDK自帶的實現,則需要作如下調整。
首先,Data接口和FutureData就不需要了,JDK幫我們實現了。
其次,RealData改為這樣:
**[java]**?[view plain](http://blog.csdn.net/ghuil/article/details/41048017# "view plain")?[copy](http://blog.csdn.net/ghuil/article/details/41048017# "copy")
1. import?java.util.concurrent.Callable;??
2. ??
3. public?class?RealData?implements?Callable?{??
4. ????protected?String?data;??
5. ??
6. ????public?RealData(String?data)?{??
7. ????????this.data?=?data;??
8. ????}??
9. ??
10. ????@Override??
11. ????public?String?call()?throws?Exception?{??
12. ????????//利用sleep方法來表示真是業務是非常緩慢的??
13. ????????try?{??
14. ????????????Thread.sleep(1000);??
15. ????????}?catch?(InterruptedException?e)?{??
16. ????????????e.printStackTrace();??
17. ????????}??
18. ????????return?data;??
19. ????}??
20. }??
最后,在測試運行時,這樣調用:
**[java]**?[view plain](http://blog.csdn.net/ghuil/article/details/41048017# "view plain")?[copy](http://blog.csdn.net/ghuil/article/details/41048017# "copy")
1. import?java.util.concurrent.ExecutorService;??
2. import?java.util.concurrent.Executors;??
3. import?java.util.concurrent.FutureTask;??
4. ??
5. public?class?Application?{??
6. ????public?static?void?main(String[]?args)?throws?Exception?{??
7. ????????FutureTask?futureTask?=???
8. ????????????????new?FutureTask(new?RealData("name"));??
9. ????????ExecutorService?executor?=???
10. ????????????????Executors.newFixedThreadPool(1);?//使用線程池??
11. ????????//執行FutureTask,相當于上例中的client.request("name")發送請求??
12. ????????executor.submit(futureTask);??
13. ????????//這里可以用一個sleep代替對其他業務邏輯的處理??
14. ????????//在處理這些業務邏輯過程中,RealData也正在創建,從而充分了利用等待時間??
15. ????????Thread.sleep(2000);??
16. ????????//使用真實數據??
17. ????????//如果call()沒有執行完成依然會等待??
18. ????????System.out.println("數據="?+?futureTask.get());??
19. ????}??
20. }??
本文完。轉載請注明出處。
參考文獻
葛一鳴,Java程序性能優化.清華大學出版社.
- JVM
- 深入理解Java內存模型
- 深入理解Java內存模型(一)——基礎
- 深入理解Java內存模型(二)——重排序
- 深入理解Java內存模型(三)——順序一致性
- 深入理解Java內存模型(四)——volatile
- 深入理解Java內存模型(五)——鎖
- 深入理解Java內存模型(六)——final
- 深入理解Java內存模型(七)——總結
- Java內存模型
- Java內存模型2
- 堆內內存還是堆外內存?
- JVM內存配置詳解
- Java內存分配全面淺析
- 深入Java核心 Java內存分配原理精講
- jvm常量池
- JVM調優總結
- JVM調優總結(一)-- 一些概念
- JVM調優總結(二)-一些概念
- VM調優總結(三)-基本垃圾回收算法
- JVM調優總結(四)-垃圾回收面臨的問題
- JVM調優總結(五)-分代垃圾回收詳述1
- JVM調優總結(六)-分代垃圾回收詳述2
- JVM調優總結(七)-典型配置舉例1
- JVM調優總結(八)-典型配置舉例2
- JVM調優總結(九)-新一代的垃圾回收算法
- JVM調優總結(十)-調優方法
- 基礎
- Java 征途:行者的地圖
- Java程序員應該知道的10個面向對象理論
- Java泛型總結
- 序列化與反序列化
- 通過反編譯深入理解Java String及intern
- android 加固防止反編譯-重新打包
- volatile
- 正確使用 Volatile 變量
- 異常
- 深入理解java異常處理機制
- Java異常處理的10個最佳實踐
- Java異常處理手冊和最佳實踐
- Java提高篇——對象克隆(復制)
- Java中如何克隆集合——ArrayList和HashSet深拷貝
- Java中hashCode的作用
- Java提高篇之hashCode
- 常見正則表達式
- 類
- 理解java類加載器以及ClassLoader類
- 深入探討 Java 類加載器
- 類加載器的工作原理
- java反射
- 集合
- HashMap的工作原理
- ConcurrentHashMap之實現細節
- java.util.concurrent 之ConcurrentHashMap 源碼分析
- HashMap的實現原理和底層數據結構
- 線程
- 關于Java并發編程的總結和思考
- 40個Java多線程問題總結
- Java中的多線程你只要看這一篇就夠了
- Java多線程干貨系列(1):Java多線程基礎
- Java非阻塞算法簡介
- Java并發的四種風味:Thread、Executor、ForkJoin和Actor
- Java中不同的并發實現的性能比較
- JAVA CAS原理深度分析
- 多個線程之間共享數據的方式
- Java并發編程
- Java并發編程(1):可重入內置鎖
- Java并發編程(2):線程中斷(含代碼)
- Java并發編程(3):線程掛起、恢復與終止的正確方法(含代碼)
- Java并發編程(4):守護線程與線程阻塞的四種情況
- Java并發編程(5):volatile變量修飾符—意料之外的問題(含代碼)
- Java并發編程(6):Runnable和Thread實現多線程的區別(含代碼)
- Java并發編程(7):使用synchronized獲取互斥鎖的幾點說明
- Java并發編程(8):多線程環境中安全使用集合API(含代碼)
- Java并發編程(9):死鎖(含代碼)
- Java并發編程(10):使用wait/notify/notifyAll實現線程間通信的幾點重要說明
- java并發編程-II
- Java多線程基礎:進程和線程之由來
- Java并發編程:如何創建線程?
- Java并發編程:Thread類的使用
- Java并發編程:synchronized
- Java并發編程:Lock
- Java并發編程:volatile關鍵字解析
- Java并發編程:深入剖析ThreadLocal
- Java并發編程:CountDownLatch、CyclicBarrier和Semaphore
- Java并發編程:線程間協作的兩種方式:wait、notify、notifyAll和Condition
- Synchronized與Lock
- JVM底層又是如何實現synchronized的
- Java synchronized詳解
- synchronized 與 Lock 的那點事
- 深入研究 Java Synchronize 和 Lock 的區別與用法
- JAVA編程中的鎖機制詳解
- Java中的鎖
- TreadLocal
- 深入JDK源碼之ThreadLocal類
- 聊一聊ThreadLocal
- ThreadLocal
- ThreadLocal的內存泄露
- 多線程設計模式
- Java多線程編程中Future模式的詳解
- 原子操作(CAS)
- [譯]Java中Wait、Sleep和Yield方法的區別
- 線程池
- 如何合理地估算線程池大小?
- JAVA線程池中隊列與池大小的關系
- Java四種線程池的使用
- 深入理解Java之線程池
- java并發編程III
- Java 8并發工具包漫游指南
- 聊聊并發
- 聊聊并發(一)——深入分析Volatile的實現原理
- 聊聊并發(二)——Java SE1.6中的Synchronized
- 文件
- 網絡
- index
- 內存文章索引
- 基礎文章索引
- 線程文章索引
- 網絡文章索引
- IOC
- 設計模式文章索引
- 面試
- Java常量池詳解之一道比較蛋疼的面試題
- 近5年133個Java面試問題列表
- Java工程師成神之路
- Java字符串問題Top10
- 設計模式
- Java:單例模式的七種寫法
- Java 利用枚舉實現單例模式
- 常用jar
- HttpClient和HtmlUnit的比較總結
- IO
- NIO
- NIO入門
- 注解
- Java Annotation認知(包括框架圖、詳細介紹、示例說明)