Java多線程實現異步調用

在Java平臺,實現異步調用的角色有如下三個角色:調用者、 提貨單 、真實數據,一個調用者在調用耗時操作,不能立即返回數據時,先返回一個提貨單

.然后在過一斷時間后憑提貨單來獲取真正的數據.去蛋糕店買蛋糕,不需要等蛋糕做出來(假設現做要很長時間),只需要領個提貨單就可以了(去干別的

事情),等到蛋糕做好了,再拿提貨單取蛋糕就可以了。

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. package?com.somnus.async;??
  2. ??
  3. /**?
  4. ?*??
  5. ?*?@Description:?顧客?
  6. ?*?@author?Somnus?
  7. ?*?@date?2016年3月9日?下午7:20:41?
  8. ?*?@version?1.0?
  9. ?*/??
  10. public?class?Customer?{??
  11. ??
  12. ????public?static?void?main(String[]?args)?{??
  13. ????????System.out.println("main?BEGIN");??
  14. ????????CakeShop?host?=?new?CakeShop();??
  15. ????????Cake?cake1?=?host.request(10,?'A');??
  16. ????????Cake?cake2?=?host.request(20,?'B');??
  17. ????????Cake?cake3?=?host.request(30,?'C');??
  18. ????????System.out.println("main?otherJob?BEGIN");??
  19. ????????try?{??
  20. ????????????Thread.sleep(2000);??
  21. ????????}?catch?(InterruptedException?e)?{??
  22. ????????}??
  23. ??
  24. ????????System.out.println("main?otherJob?END");??
  25. ????????System.out.println("cake1?=?"?+?cake1.getCake());??
  26. ????????System.out.println("cake2?=?"?+?cake2.getCake());??
  27. ????????System.out.println("cake3?=?"?+?cake3.getCake());??
  28. ????????System.out.println("main?END");??
  29. ??
  30. ????}??
  31. }??

?

  這里的Customer類就相當于“顧客”,CakeShop就相當于“蛋糕店”,顧客向“蛋糕店”定蛋糕就相當于“發請求request”,返回的數據cake是

DeliveryOrder的實例,就相當于提貨單,而不是真正的“蛋糕”。在過一段時間后(sleep一段時間后),調用data1.getContent(),也就是拿提貨單獲取

執行結果。

?

  下面來看一下,顧客定蛋糕后,蛋糕店做了什么:

?

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. package?com.somnus.async;??
  2. ??
  3. /**?
  4. ?*?@Description:?TODO?
  5. ?*?@author?Somnus?
  6. ?*?@date?2016年3月9日?下午7:21:32?
  7. ?*?@version?1.0?
  8. ?*/??
  9. public?class?CakeShop?{??
  10. ??
  11. ????public?Data?request(final?int?count,?final?char?c)?{??
  12. ??
  13. ????????System.out.println("request("?+?count?+?",?"?+?c?+?")?BEGIN");??
  14. ????????//?(1)?建立DeliveryOrder的實體??
  15. ????????final?DeliveryOrder?order?=?new?DeliveryOrder();??
  16. ??????????
  17. ????????//?(2)?為了建立RealData的實體,啟動新的線程??
  18. ????????new?Thread()?{??
  19. ????????????public?void?run()?{??
  20. ????????????????//在匿名內部類中使用count、order、c。??
  21. ????????????????CakeBaker?cakeBaker?=?new?CakeBaker(count,?c);??
  22. ????????????????order.setCakeBaker(cakeBaker);??
  23. ????????????}??
  24. ????????}.start();??
  25. ????????System.out.println("request("?+?count?+?",?"?+?c?+?")?END");??
  26. ??????????
  27. ????????//?(3)?取回FutureData實體,作為傳回值??
  28. ????????return?order;??
  29. ??
  30. ????}??
  31. }??



?

  CakeShop("蛋糕店")在接到請求后,先生成了“提貨單”DeliveryOrder的實例order,然后命令“蛋糕師傅CakeBaker去做蛋糕,CakeBaker相當于起

個線程去做蛋糕了。然后host返回給顧客的僅僅是“提貨單”future,而不是蛋糕。當蛋糕做好后,蛋糕師傅才能給對應的“提貨單”蛋糕,也就

是order.setCakeBaker(cakeBaker);。


  下面來看看蛋糕師傅是怎么做蛋糕的:

  建立一個字符串,包含count個c字符,為了表現出犯法需要花費一些時間,使用了sleep。

?

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. package?com.somnus.async;??
  2. ??
  3. /**?
  4. ?*?@Description:?蛋糕師傅?
  5. ?*?@author?Somnus?
  6. ?*?@date?2016年3月9日?下午7:22:52?
  7. ?*?@version?1.0?
  8. ?*/??
  9. public?class?CakeBaker?implements?Cake?{??
  10. ????private?final?String?cake;??
  11. ??
  12. ????public?CakeBaker(int?count,?char?c)?{??
  13. ????????System.out.println("making?cake("?+?count?+?",?"?+?c?+?")?BEGIN");??
  14. ????????char[]?buffer?=?new?char[count];??
  15. ????????for?(int?i?=?0;?i?<?count;?i++)?{??
  16. ????????????buffer[i]?=?c;??
  17. ????????????try?{??
  18. ????????????????Thread.sleep(3000);??
  19. ????????????}?catch?(InterruptedException?e)?{??
  20. ????????????????e.printStackTrace();??
  21. ????????????}??
  22. ????????}??
  23. ????????System.out.println("making?cake("?+?count?+?",?"?+?c?+?")?END");??
  24. ????????this.cake?=?new?String(buffer);??
  25. ????}??
  26. ??
  27. ????public?String?getCake()?{??
  28. ????????return?cake;??
  29. ????}??
  30. ??
  31. }??



?

  現在來看看“提貨單”order是怎么與蛋糕"cake"對應的:

[java]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. package?com.somnus.async;??
  2. ??
  3. /**?
  4. ?*?@Description:?提貨單?
  5. ?*?@author?Somnus?
  6. ?*?@date?2016年3月9日?下午7:25:06?
  7. ?*?@version?1.0?
  8. ?*/??
  9. public?class?DeliveryOrder?implements?Cake?{??
  10. ????private?CakeBaker?cakeBaker?=?null;??
  11. ??
  12. ????private?boolean?ready?=?false;??
  13. ??
  14. ????public?synchronized?void?setCakeBaker(CakeBaker?cakeBaker)?{??
  15. ????????if?(ready)?{??
  16. ????????????return;?//?防止setCakeBaker被調用兩次以上。??
  17. ????????}??
  18. ????????this.cakeBaker?=?cakeBaker;??
  19. ????????this.ready?=?true;??
  20. ????????notifyAll();??
  21. ????}??
  22. ??
  23. ????public?synchronized?String?getCake()?{??
  24. ????????while?(!ready)?{??
  25. ????????????try?{??
  26. ????????????????wait();??
  27. ????????????}?catch?(InterruptedException?e)?{??
  28. ????????????????e.printStackTrace();??
  29. ????????????}??
  30. ????????}??
  31. ????????return?cakeBaker.getCake();??
  32. ????}??
  33. ??
  34. }??


  顧客做完自己的事情后,會拿著自己的“提貨單”來取蛋糕:

[html]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. System.out.println("cake1?=?"?+?cake1.getCake());??


  這時候如果蛋糕沒做好,就只好等了:

[html]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. while?(!ready)?{??
  2. ????try?{??
  3. ????????wait();??
  4. ????}?catch?(InterruptedException?e)?{??
  5. ????????e.printStackTrace();??
  6. ????}??
  7. }??


  //等做好后才能取到

[html]?view plaincopy
print?在CODE上查看代碼片派生到我的代碼片
  1. return?cakeBaker.getCake();??


  程序分析

  對于每個請求,host都會生成一個線程,這個線程負責生成顧客需要的“蛋糕”。在等待一段時間以后,如果蛋糕還沒有做好,顧客還必須等待。

直到“蛋糕被做好”,也就是


  order.setCakeBaker(cakeBaker);執行以后,顧客才能拿走蛋糕。

  每個線程只是專門負責制作特定顧客所需要的“蛋糕”。也就是顧客A對應著蛋糕師傅A,顧客B對應著蛋糕師傅B。即使顧客B的蛋糕被先做好了,

顧客A也只能等待蛋糕師傅A把蛋糕做好。換句話說,顧客之間沒有競爭關系。

?

  類DeliveryOrder的兩個方法被設置為synchronized,實際上蛋糕師傅A與顧客A之間的互斥關系,也就是顧客A必須等待蛋糕師傅A把蛋糕做好后,

才能拿走,而與蛋糕師傅B是否做好了蛋糕沒有關系。

轉載于:https://www.cnblogs.com/tuojunjie/p/6836677.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455702.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455702.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455702.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

sql server 2008 r2卸載重裝_免費下載:Intouch軟件、Windows操作系統、SQL數據庫,VB6.0、C#...

為大家整理了常用的Windows操作系統和安裝軟件&#xff0c;基本上都是經過我們項目測試OK的版本&#xff0c;以后項目調試就齊全了&#xff0c;不用再“東奔西走”&#xff0c;“小鹿亂撞”了。整理不易&#xff0c;若對您有幫助請關注并轉發&#xff0c;以便幫助到更多的人。I…

Android ToolBar 使用完全解析

ToolBar簡介 ToolBar是Android 5.0推出的一個新的導航控件用于取代之前的ActionBar&#xff0c;由于其高度的可定制性、靈活性、具有Material Design風格等優點&#xff0c;越來越多的應用也用上了ToolBar&#xff0c;比如常用的知乎軟件其頂部導航欄正是使用ToolBar。官方考慮…

【零散積累】傳輸文件(sz/rz/scp命令)

來自wiki遷移頁面路徑&#xff1a;劉旺的主頁 / 個人零散積累 / 01> 傳輸文件&#xff08;sz/rz/scp命令&#xff09; 工作中的傳輸文件會出現在linux之間&#xff0c;或者linux與windows之間。 一、怎么實現linux與windows之間的文件傳輸&#xff1f; 1.sz和rz是什么 s…

x264_macroblock_cache_load()

功能:完成將已編碼數據參數和待編碼數據裝入到h->mb.cache中,下圖是BUF中存儲的數據在以MB為單位的時候的存儲順序 x264_macroblock_cache_load( h, i_mb_x, i_mb_y );//是把當前宏塊的up宏塊和left宏塊的intra4x4_pred_mode&#xff0c;non_zero_count加載進來&#xff0c…

U(優)盤安裝FreeBSD-9.0+GNOME_lite桌面

貼圖在我的主頁&#xff1a;http://hi.baidu.com/daodej/item/26313f4fc3db51ef1f19bcc6 修訂于&#xff1a;2012/07/04 標題&#xff1a;U(優)盤安裝FreeBSD-9.0GNOME_lite桌面&#xff0c;boot0啟動XP(Windows)、FreeBSD、Ubuntu(Linux)三系統 【黑括號表示說明&#xff0c;中…

【零散積累】 vim常用操作

類型 操作 含義 刪除 dd 刪除游標所在的一整行(常用) ndd n為數字。刪除光標所在的向下n行&#xff0c;例如20dd則是刪除光標所在的向下20行 d1G 刪除光標所在到第一行的所有數據 dG 刪除光標所在到最后一行的所有數據 d$ 刪除光標所在處&#xff0c;到該…

生活中常見物聯網實例_物聯網網關常見問題解答(一)

1.為什么物聯網解決方案需要網關&#xff1f;物聯網網關彌合了設備&#xff0c;傳感器&#xff0c;設備&#xff0c;系統和云之間的通信鴻溝。通過系統地連接云&#xff0c;物聯網網關提供了本地處理和存儲&#xff0c;并具有基于傳感器輸入的數據自主控制現場設備的功能。物聯…

predict_16x16[i_mode]( p_dst, i_stride )lowres

h->predict_16x16[i_mode]( p_dst, i_stride ); 計算對應預測模式時的預測采樣值。輸出放到dst指向的數組中。Pred0ct_16x16是7個元素指向的數組&#xff0c;數組的每個元素是一個指向函數的指針變量&#xff0c;在x264_predict_16x16_init函數初始這個指針數組。7個元素分…

【零散積累】shell腳本學習

來自wiki遷移頁面路徑&#xff1a;劉旺的主頁 / 個人零散積累 / 03> shell腳本學習 case Shell case語句&#xff08;多分支條件判斷&#xff09; $( ) Linux—shell中$(( ))、$( )、與${ }的區別 - chengd - 博客園 在bash中&#xff0c;$( )與 &#xff08;反引號&…

mysql 表鎖-解鎖

遇到問題“”用工具navicat打開一張表的時候&#xff0c;有的時候會發現這張表怎么打不開&#xff0c;關了navicat工具&#xff0c;再打開&#xff0c;也是同樣的狀態。查看表鎖&#xff1a;show OPEN TABLES where In_use > 0;查看是否是表鎖住了。-- 查看進程號 show proc…

alsa 測試 linux_Electron 構建步驟 (Linux)

遵循下面的引導&#xff0c;在 Linux 上構建 Electron .PrerequisitesPython 2.7.x. 一些發行版如 CentOS 仍然使用 Python 2.6.x &#xff0c;所以或許需要 check 你的 Python 版本&#xff0c;使用 python -V.Node.js v0.12.x. 有很多方法來安裝 Node. 可以從 Node.js下載原文…

JavaScript中的數學對象Math

js數學對象Math //四舍五入 var res Math.round(5.921);//獲取最大值 var res Math.max(10,23,523,43,65,46,32,32);//獲取最小值 var res Math.min(12312,324,32,42,3,23,412,4332,21,3,-1);//獲取絕對值 var res Math.abs(-100);//退一取整 var res Math.floor(1.9);//…

centos7-安裝mysql5.6.36

本地安裝了mysql5.7, 但和springboot整合jpa時會出現 hibernateException, 不知道為什么, 換個mysql5.6版本的mysql, 源碼安裝, cmake一直過不去, 后來改成rpm安裝 1, 獲取mysql5.6 ftp://ftp.mirrorservice.org/sites/ftp.mysql.com/Downloads/MySQL-5.6/ 下載: 解壓: 其中…

mad的問題匯總

Q&#xff1a;我想將I幀的預測圖像和原始圖像的平均絕對誤差給輸出來&#xff0c;請問這個在JM86中需要在哪一點改動呢&#xff1f;謝謝 A&#xff1a; 差值保存在diffy中&#xff1a; diffy[j][i] imgY_org[img->opix_yj][img->opix_xi] - pred[j][i]; 分析MAD不知道程…

迷之騷縮寫

搜集一些 GitHub 常見騷縮寫&#xff0c;以備查詢使用。 原文鏈接&#xff1a;LGTM? 那些迷之縮寫 PR: Pull Request. 拉取請求&#xff0c;給其他項目提交代碼LGTM: Looks Good To Me. 朕知道了 代碼已經過 review&#xff0c;可以合并SGTM: Sounds Good To Me. 和上面那句意…

github設置中文_靜態博客托管圖片至 GitHub

從 MWeb 切換到靜態博客 Jekyll 之后&#xff0c;我就面臨一個問題&#xff0c;這在很久之前使用 Hexo 同樣遇過的&#xff1a;圖片托管在何處。MWeb 的解決方式很棒&#xff0c;直接插入圖片&#xff0c;推送到 Github 后亦能正常引用并顯示&#xff0c;無需圖床或者借助第三方…

JavaScript中的正則

js正則 正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串, 正則表達式通常被用來檢索、替換那些符合某個模式的文本 聲明方式 普通字符 new RegExp();/hehe/轉義字符 \w \W \d \D \s \S var reg /\w/;//單個的字母數字下劃線 var reg /\W/;…

SQL注入【sqli靶場第23-28關】(七)

★★免責聲明★★ 文章中涉及的程序(方法)可能帶有攻擊性&#xff0c;僅供安全研究與學習之用&#xff0c;讀者將信息做其他用途&#xff0c;由Ta承擔全部法律及連帶責任&#xff0c;文章作者不承擔任何法律及連帶責任。 0、總體思路 先確認是否可以SQL注入&#xff0c;使用單…

Linq中string轉int的方法

Linq中string轉int的方法 在做批量刪除時&#xff0c;需把一串id值所對應的數據刪除&#xff0c;調試出現問題&#xff1a; Linq語句中如果使用ToString()進行類型轉換,編譯時不會報錯,但執行時會出現如下錯誤&#xff1a; “LINQ to Entities 不識別方法"System.String T…

名稱縮寫第二波

1 公司內部 縮寫 全稱 中文 說明 PMproduct manager產品經理RDResearch and Development研發工程師FEFrontend Engineer前端工程師UEUser Experience用戶體驗設計師QAquality assurance質量保證&#xff0c;測試OP operator 運維工程師EEEngeering Excellence工程效率部ETEn…