Async Mode: Future使用
Future 模式(異步調用)
http://eyesmore.iteye.com/blog/243648
在多線程交互的中2,經常有一個線程需要得到另個一線程的計算結果,我們常用的是Future異步模式來加以解決。
Future顧名思意,有點像期貨市場的“期權”,是“對未來的一種憑證”,例如當我們買了某個房地產開發商的期房,交錢之后,開發商會給我們一個憑證(期權),這個憑證告訴我們等明年某個時候拿這個憑證就可以拿到我們所需要的房子,但是現在房子還沒建好。市場上之所以有“期貨”,也正由于有這種需求,才有這種供給。
?
這種應用在GUI上用的比較多,在設計模式中一般稱為“虛擬代理模式”。
?
例如:現在有個這樣的需求,Client向Server提交一個Request(int count,char c),希望獲取一個由count個字符c構造出來的字符串。比如發送Request(10,'K'),那么反饋字符串“KKKKKKKKKK”,但是我們假設這個生成字符串的過程很費時間。
?
于是,為了獲取比較好的交互性,我們的Server收到請求后,先構造一個FutureData,并把這個所謂的“期權(未來憑證)”反饋給Client;于此同時,通過另一個并發線程去構造一個真正的字符串RealData,并在構造完畢后,RealData給FutureData報告一個消息,說數據(期房)已經準備好了,此時Client可以通過期權拿到期房,但是假如我們的Client比較著急,還沒等房子假好的時,就想要房子,怎么辦呢?這個時候我們可以阻塞Client所在的線程,讓Client等待,直到最后RealData通知FutureData說房子好了,才返回。
這里的要點:
(1)Server先給Client一個“期權”,同時開一個線程去干活建房子(未來的“現房”);
(2)當“現房”RealData準備好了的時候,如何告訴FutureData說已經準備好了。(本處采用“回調過程”(借用觀察者模式,來實現回調))
(3)如果客戶比較著急,現房還沒準備好的時候,就要取房,怎么辦?? 本處采用“阻塞”。
?
Data(公共數據接口)
?
Java代碼??
1.? package?com.umpay.future;??
2.? ??
3.? public?interface?Data?{??
4.? ????public?abstract?String?getContent();??
5.? }??
?
FutureData(期權)
?
Java代碼??
1.? package?com.umpay.future.extend;??
2.? ??
3.? import?java.util.Observable;??
4.? import?java.util.Observer;??
5.? ??
6.? import?com.umpay.future.Data;??
7.? ??
8.? public?class?FutureData2?implements?Data,Observer?{??
9.? ??
10. ????/**??
11. ?????*?存放真實數據,并且標志真正的數據是否已經準備完畢?
12. ?????*?被多線程享受?
13. ?????*?如果realData2==null,表示數據還準備好?
14. ?????*?*/??
15. ????private?volatile?RealData2?realData2?=?null;??
16. ????/**?
17. ?????*?查看真正的數據是否準備完畢?
18. ?????*?*/??
19. ????public?boolean?isFinished()?{??
20. ????????return?realData2?!=?null;??
21. ????}??
22. ??????
23. ????/**?
24. ?????*?如果數據已經準備好,則返回真正的數據;?
25. ?????*?否則,阻塞調用線程,直到數據準備完畢后,才返回真實數據;?
26. ?????*?*/??
27. ????public?String?getContent()?{??
28. ????????synchronized?(mutex)?{??
29. ????????????while(!isFinished())?{//只要數據沒有準備完畢,就阻塞調用線程??
30. ????????????????try?{??
31. ????????????????????mutex.wait();??
32. ????????????????}?catch?(InterruptedException?e)?{??
33. ????????????????????e.printStackTrace();??
34. ????????????????}??
35. ????????????}??
36. ????????????return?realData2.getContent();??
37. ????????}??
38. ????}??
39. ??
40. ????/**?
41. ?????*??當?RealData2?準備完數據后,RealData2?應該通知?FutureData2?數據準備完畢。?
42. ?????*??并在輸入參數?realData?傳入真實數據,在參數?event?傳入事件(比如數據如期準備好了,或出了什么異常)?
43. ?????*?
44. ?????*??@param??realData????真實的數據?
45. ?????*??@param??event???????事件類型?
46. ?????*?*/??
47. ????public?void?update(Observable?realData,?Object?event)?{??
48. ????????System.out.println("通知...."+event);??
49. ????????if(!(realData?instanceof?RealData2))?{??
50. ????????????throw?new?IllegalArgumentException("主題的數據類型必須是RealData2");??
51. ????????}??
52. ????????if(!(event?instanceof?String))?{??
53. ????????????throw?new?IllegalArgumentException("事件的數據類型必須是String");??
54. ????????}??
55. ????????synchronized?(mutex)?{??
56. ????????????if(isFinished())?{??
57. ????????????????mutex.notifyAll();??
58. ????????????????return;//如果數據已經準備好了,直接返回.??
59. ????????????}??
60. ????????????if("Finished".equals(event))?{??
61. ????????????????realData2?=?(RealData2)realData;//數據準備好了的時候,便可以通知數據準備好了??
62. ????????????????mutex.notifyAll();//喚醒被阻塞的線程??
63. ????????????}???
64. ????????}??
65. ????}??
66. ??
67. ????private?Object?mutex?=?new?Object();??
68. }??
?
RealData(實際數據)
?
Java代碼??
1.? package?com.umpay.future.extend;??
2.? ??
3.? import?java.util.Observable;??
4.? ??
5.? import?com.umpay.future.Data;??
6.? ??
7.? public?class?RealData2?extends?Observable?implements?Data?{??
8.? ??
9.? ????private?String?content;??
10. ??
11. ????public?RealData2()?{??
12. ??????????
13. ????}??
14. ??????
15. ????public?void?createRealData2(int?count,?char?c)?{??
16. ????????System.out.println("????????making?RealData("?+?count?+?",?"?+?c??
17. ????????????????+?")?BEGIN");??
18. ????????char[]?buffer?=?new?char[count];??
19. ????????for?(int?i?=?0;?i?<?count;?i++)?{??
20. ????????????buffer[i]?=?c;??
21. ????????????try?{??
22. ????????????????Thread.sleep(100);??
23. ????????????}?catch?(InterruptedException?e)?{??
24. ????????????}??
25. ????????}??
26. ????????System.out.println("????????making?RealData("?+?count?+?",?"?+?c??
27. ????????????????+?")?END");??
28. ????????this.content?=?new?String(buffer);??
29. ??????????
30. ????????//真實數據準備完畢了,通知FutureData2說數據已經準備好了.??
31. ????????setChanged();//必須先設置本對象的狀態發生了變化,并且通知所有的觀察者??
32. ????????notifyObservers("Finished");??
33. ????}??
34. ??????
35. ??
36. ????public?String?getContent()?{??
37. ????????return?content;??
38. ????}??
39. }??
?
?
服務端代碼:
?
Java代碼??
1.? package?com.umpay.future.extend;??
2.? ??
3.? import?com.umpay.future.Data;??
4.? ??
5.? public?class?HostServer2?{??
6.? ??
7.? ????public?Data?request(final?int?count,?final?char?c)?{??
8.? ????????System.out.println("????request("?+?count?+?",?"?+?c?+?")?BEGIN");??
9.? ??
10. ????????//?(1)?建立FutureData的實體??
11. ????????final?FutureData2?future2?=?new?FutureData2();??
12. ??
13. ????????//?(2)?為了建立RealData的實體,啟動新的線程??
14. ????????new?Thread()?{??
15. ????????????public?void?run()?{??
16. ????????????????RealData2?realdata2?=?new?RealData2();??
17. ????????????????realdata2.addObserver(future2);//以便當RealData2把數據準備完畢后,通過該回調口子,通知FutureData2表示數據已經貯備好了??
18. ????????????????realdata2.createRealData2(count,?c);??
19. ????????????}??
20. ????????}.start();??
21. ??
22. ????????System.out.println("????request("?+?count?+?",?"?+?c?+?")?END");??
23. ??
24. ????????//?(3)?取回FutureData實體,作為傳回值??
25. ????????return?future2;??
26. ????}??
27. ??
28. }??
?
客戶端代碼:
?
Java代碼??
1.? package?com.umpay.future;??
2.? ??
3.? import?com.umpay.future.extend.HostServer2;??
4.? ??
5.? public?class?MainClient?{??
6.? ????public?static?void?main(String[]?args)?{??
7.? //??????testHostServer();??
8.? ????????testHostServer2();??
9.? ????}??
10. ??????
11. ????static?void?testHostServer()?{??
12. ????????System.out.println("main?BEGIN");??
13. ????????HostServer?hostServer?=?new?HostServer();??
14. ????????Data?data1?=?hostServer.request(10,?'A');??
15. ????????Data?data2?=?hostServer.request(20,?'B');??
16. ????????Data?data3?=?hostServer.request(30,?'C');??
17. ??
18. ????????System.out.println("main?otherJob?BEGIN");??
19. //????????try?{??
20. //????????????Thread.sleep(2000);??
21. //????????}?catch?(InterruptedException?e)?{??
22. //????????}??
23. ????????System.out.println("main?otherJob?END");??
24. ??
25. ????????System.out.println("data1?=?"?+?data1.getContent());??
26. ????????System.out.println("data2?=?"?+?data2.getContent());??
27. ????????System.out.println("data3?=?"?+?data3.getContent());??
28. ????????System.out.println("main?END");??
29. ??
30. ????}??
31. ??
32. ????static?void?testHostServer2()?{??
33. ????????System.out.println("main?BEGIN");??
34. ????????HostServer2?hostServer2?=?new?HostServer2();??
35. ????????Data?data1?=?hostServer2.request(10,?'A');??
36. ????????Data?data2?=?hostServer2.request(20,?'B');??
37. ????????Data?data3?=?hostServer2.request(30,?'C');??
38. ??
39. ????????System.out.println("main?otherJob?BEGIN");??
40. //????????try?{??
41. //????????????Thread.sleep(2000);??
42. //????????}?catch?(InterruptedException?e)?{??
43. //????????}??
44. ????????System.out.println("main?otherJob?END");??
45. ??
46. ????????System.out.println("data1?=?"?+?data1.getContent());??
47. ????????System.out.println("data2?=?"?+?data2.getContent());??
48. ????????System.out.println("data3?=?"?+?data3.getContent());??
49. ????????System.out.println("main?END");??
50. ??
51. ????}??
52. }??
?
?
?
Java程序執行超時——Future接口介紹
http://westyi.iteye.com/blog/714935
在Java中,如果需要設定代碼執行的最長時間,即超時,可以用Java線程池ExecutorService類配合Future接口來實現。 Future接口是Java標準API的一部分,在java.util.concurrent包中。Future接口是Java線程Future模式的實 現,可以來進行異步計算。
Future模式可以這樣來描述:我有一個任務,提交給了Future,Future替我完成這個任務。期間我自己可以去做任何想做的事情。一段時 間之后,我就便可以從Future那兒取出結果。就相當于下了一張訂貨單,一段時間后可以拿著提訂單來提貨,這期間可以干別的任何事情。其中Future 接口就是訂貨單,真正處理訂單的是Executor類,它根據Future接口的要求來生產產品。
Future接口提供方法來檢測任務是否被執行完,等待任務執行完獲得結果,也可以設置任務執行的超時時間。這個設置超時的方法就是實現Java程 序執行超時的關鍵。
Future接口是一個泛型接口,嚴格的格式應該是Future<V>,其中V代表了Future執行的任務返回值的類型。 Future接口的方法介紹如下:
·???????? boolean?cancel?(boolean mayInterruptIfRunning) 取消任務的執行。參數指定是否立即中斷任務執行,或者等等任務結束
·???????? boolean?isCancelled?() 任務是否已經取消,任務正常完成前將其取消,則返回?true
·???????? boolean?isDone?() 任務是否已經完成。需要注意的是如果任務正常終止、異常或取消,都將返回true
·???????? V?get?() throws InterruptedException, ExecutionException? 等待任務執行結束,然后獲得V類型的結果。InterruptedException 線程被中斷異常, ExecutionException任務執行異常,如果任務被取消,還會拋出CancellationException
·???????? V?get?(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 同上面的get功能一樣,多了設置超時時間。參數timeout指定超時時間,uint指定時間的單位,在枚舉類TimeUnit中有相關的定義。如果計 算超時,將拋出TimeoutException
Future的實現類有java.util.concurrent.FutureTask<V>即 javax.swing.SwingWorker<T,V>。通常使用FutureTask來處理我們的任務。FutureTask類同時又 實現了Runnable接口,所以可以直接提交給Executor執行。使用FutureTask實現超時執行的代碼如下:
Java代碼??
1.? ExecutorService?executor?=?Executors.newSingleThreadExecutor();??
2.? FutureTask<String>?future?=??
3.? ???????new?FutureTask<String>(new?Callable<String>()?{//使用Callable接口作為構造參數??
4.? ?????????public?String?call()?{??
5.? ???????????//真正的任務在這里執行,這里的返回值類型為String,可以為任意類型??
6.? ???????}});??
7.? executor.execute(future);??
8.? //在這里可以做別的任何事情??
9.? try?{??
10. ????result?=?future.get(5000,?TimeUnit.MILLISECONDS);?//取得結果,同時設置超時執行時間為5秒。同樣可以用future.get(),不設置執行超時時間取得結果??
11. }?catch?(InterruptedException?e)?{??
12. ????futureTask.cancel(true);??
13. }?catch?(ExecutionException?e)?{??
14. ????futureTask.cancel(true);??
15. }?catch?(TimeoutException?e)?{??
16. ????futureTask.cancel(true);??
17. }?finally?{??
18. ????executor.shutdown();??
19. }??
? ?
?
不直接構造Future對象,也可以使用ExecutorService.submit方法來獲得Future對象,submit方法即支持以 Callable接口類型,也支持Runnable接口作為參數,具有很大的靈活性。使用示例如下:
Java代碼??
1.? ExecutorService?executor?=?Executors.newSingleThreadExecutor();??
2.? FutureTask<String>?future?= executor.submit(??
3.? ???new?Callable<String>()?{//使用Callable接口作為構造參數??
4.? ???????public?String?call()?{??
5.? ??????//真正的任務在這里執行,這里的返回值類型為String,可以為任意類型??
6.? ???}});??
7.? //在這里可以做別的任何事情??
8.? //同上面取得結果的代碼??
??
利用Future接口實現程序執行超時大致用法就這么多,改天需要研究下Future接口的內部實現,特別是設定執行超時的實現。
?
轉載于:https://www.cnblogs.com/DreamSea-for-Jimmy/archive/2011/09/06/2168572.html
總結
以上是生活随笔為你收集整理的Async Mode: Future使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何实施好基于MOSS的企业搜索项目(上
- 下一篇: 乔布斯最伟大的贡献是什么