生活随笔
收集整理的這篇文章主要介紹了
Java多线程实现异步调用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在Java平臺,實現異步調用的角色有如下三個角色:調用者、 提貨單 、真實數據,一個調用者在調用耗時操作,不能立即返回數據時,先返回一個提貨單
.然后在過一斷時間后憑提貨單來獲取真正的數據.去蛋糕店買蛋糕,不需要等蛋糕做出來(假設現做要很長時間),只需要領個提貨單就可以了(去干別的
事情),等到蛋糕做好了,再拿提貨單取蛋糕就可以了。
[java]?view plaincopy print?
package?com.somnus.async;????public?class?Customer?{????????public?static?void?main(String[]?args)?{??????????System.out.println("main?BEGIN");??????????CakeShop?host?=?new?CakeShop();??????????Cake?cake1?=?host.request(10,?'A');??????????Cake?cake2?=?host.request(20,?'B');??????????Cake?cake3?=?host.request(30,?'C');??????????System.out.println("main?otherJob?BEGIN");??????????try?{??????????????Thread.sleep(2000);??????????}?catch?(InterruptedException?e)?{??????????}????????????System.out.println("main?otherJob?END");??????????System.out.println("cake1?=?"?+?cake1.getCake());??????????System.out.println("cake2?=?"?+?cake2.getCake());??????????System.out.println("cake3?=?"?+?cake3.getCake());??????????System.out.println("main?END");????????}??}?? ?
這里的Customer類就相當于“顧客”,CakeShop就相當于“蛋糕店”,顧客向“蛋糕店”定蛋糕就相當于“發請求request”,返回的數據cake是
DeliveryOrder的實例,就相當于提貨單,而不是真正的“蛋糕”。在過一段時間后(sleep一段時間后),調用data1.getContent(),也就是拿提貨單獲取
執行結果。
?
下面來看一下,顧客定蛋糕后,蛋糕店做了什么:
?
[java]?view plaincopy print?
package?com.somnus.async;????public?class?CakeShop?{????????public?Data?request(final?int?count,?final?char?c)?{????????????System.out.println("request("?+?count?+?",?"?+?c?+?")?BEGIN");??????????????????final?DeliveryOrder?order?=?new?DeliveryOrder();????????????????????????????new?Thread()?{??????????????public?void?run()?{??????????????????????????????????CakeBaker?cakeBaker?=?new?CakeBaker(count,?c);??????????????????order.setCakeBaker(cakeBaker);??????????????}??????????}.start();??????????System.out.println("request("?+?count?+?",?"?+?c?+?")?END");????????????????????????????return?order;????????}??}??
?
CakeShop("蛋糕店")在接到請求后,先生成了“提貨單”DeliveryOrder的實例order,然后命令“蛋糕師傅CakeBaker去做蛋糕,CakeBaker相當于起
個線程去做蛋糕了。然后host返回給顧客的僅僅是“提貨單”future,而不是蛋糕。當蛋糕做好后,蛋糕師傅才能給對應的“提貨單”蛋糕,也就
是order.setCakeBaker(cakeBaker);。
下面來看看蛋糕師傅是怎么做蛋糕的:
建立一個字符串,包含count個c字符,為了表現出犯法需要花費一些時間,使用了sleep。
?
[java]?view plaincopy print?
package?com.somnus.async;????public?class?CakeBaker?implements?Cake?{??????private?final?String?cake;????????public?CakeBaker(int?count,?char?c)?{??????????System.out.println("making?cake("?+?count?+?",?"?+?c?+?")?BEGIN");??????????char[]?buffer?=?new?char[count];??????????for?(int?i?=?0;?i?<?count;?i++)?{??????????????buffer[i]?=?c;??????????????try?{??????????????????Thread.sleep(3000);??????????????}?catch?(InterruptedException?e)?{??????????????????e.printStackTrace();??????????????}??????????}??????????System.out.println("making?cake("?+?count?+?",?"?+?c?+?")?END");??????????this.cake?=?new?String(buffer);??????}????????public?String?getCake()?{??????????return?cake;??????}????}??
?
現在來看看“提貨單”order是怎么與蛋糕"cake"對應的:
[java]?view plaincopy print?
package?com.somnus.async;????public?class?DeliveryOrder?implements?Cake?{??????private?CakeBaker?cakeBaker?=?null;????????private?boolean?ready?=?false;????????public?synchronized?void?setCakeBaker(CakeBaker?cakeBaker)?{??????????if?(ready)?{??????????????return;?????????}??????????this.cakeBaker?=?cakeBaker;??????????this.ready?=?true;??????????notifyAll();??????}????????public?synchronized?String?getCake()?{??????????while?(!ready)?{??????????????try?{??????????????????wait();??????????????}?catch?(InterruptedException?e)?{??????????????????e.printStackTrace();??????????????}??????????}??????????return?cakeBaker.getCake();??????}????}??
顧客做完自己的事情后,會拿著自己的“提貨單”來取蛋糕:
[html]?view plaincopy print?
System.out.println("cake1?=?"?+?cake1.getCake());??
這時候如果蛋糕沒做好,就只好等了:
[html]?view plaincopy print?
while?(!ready)?{??????try?{??????????wait();??????}?catch?(InterruptedException?e)?{??????????e.printStackTrace();??????}??}??
//等做好后才能取到
[html]?view plaincopy print?
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
總結
以上是生活随笔為你收集整理的Java多线程实现异步调用的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。