新聞中心
所謂的高并發(fā)除了在架構(gòu)上的高屋建瓴,還得需要開發(fā)人員在具體業(yè)務(wù)開發(fā)中注重自己的每一行代碼、每一個細(xì)節(jié),面子有的同時,更重要的還是要有里子。

發(fā)展壯大離不開廣大客戶長期以來的信賴與支持,我們將始終秉承“誠信為本、服務(wù)至上”的服務(wù)理念,堅持“二合一”的優(yōu)良服務(wù)模式,真誠服務(wù)每家企業(yè),認(rèn)真做好每個細(xì)節(jié),不斷完善自我,成就企業(yè),實現(xiàn)共贏。行業(yè)涉及成都鑿毛機等,在重慶網(wǎng)站建設(shè)公司、全網(wǎng)整合營銷推廣、WAP手機網(wǎng)站、VI設(shè)計、軟件開發(fā)等項目上具有豐富的設(shè)計經(jīng)驗。
面對性能,我們一定要有自己的工匠精神,不可以對任何一行代碼妥協(xié)!
今天和大家分享在業(yè)務(wù)開發(fā)中如何降低接口響應(yīng)時間的一個小技巧,也是大家日常開發(fā)中比較普遍存在的一個問題,即如何提高程序的并行計算能力?
本文主要包含以下內(nèi)容:
- 順序執(zhí)行很慢
- 線程池+Future并行計算
- 使用Java8的CompletableFuture
- 使用Guava的ListenableFuture
本文包含代碼內(nèi)容較多,大家可收藏后自己跟著動手驗證一番~
順序執(zhí)行
很多時候,我們開發(fā)一個接口時候,需要調(diào)用多個方法,然后將各個方法返回的數(shù)據(jù)一起組裝返回給前端,比如這樣的:
可以看到我這里調(diào)用了4個方法,每一個方法為模擬真實耗時,所以都是延遲100ms返回一個字符串:
可想而知,我們這個接口的響應(yīng)時間一定會超過400ms,多次執(zhí)行都會在400ms多一點:
耗時:403ms耗時:409ms耗時:406ms
這就是順序執(zhí)行,也許大家覺得很Low,但是想想自己的代碼很多時候不就是這樣子的么?
線程池+Future并行計算
順序執(zhí)行確實很慢,所以我們需要并行執(zhí)行,即同時調(diào)用這四個方法,熟悉Java多線程的都知道,每個方法單獨開啟一個線程異步去執(zhí)行就好了,等全部執(zhí)行完了拿到獨立線程執(zhí)行的結(jié)果再組裝起來就可以了。
但是每次調(diào)用都需要創(chuàng)建四個線程,線程的創(chuàng)建和銷毀都是需要開銷的,所以我們就有了池化技術(shù)。
線程池、數(shù)據(jù)庫的連接池等都是采用的池化技術(shù):預(yù)先初始生成創(chuàng)建好的線程,等需要調(diào)用的時候拿來即用,線程完成工作后回歸空閑狀態(tài),等待下一次任務(wù)的到來,這樣就避免了線程頻繁的創(chuàng)建、銷毀,提高了程序的響應(yīng)性能。
所以我們在做并行計算的時候一定要充分的利用線程池的相關(guān)技術(shù),關(guān)于線程池的技術(shù)在我的另外一篇文章單獨講到,不了解的同學(xué)可以初步了解一下,面試也是必會題之一:
Java線程池基礎(chǔ)掃盲
下面我們直接上代碼:
線程池+Future
多運行幾次,看輸出響應(yīng)時間:
耗時:108ms耗時:105ms耗時:105ms
效果是不是很明顯?
直接相當(dāng)于一個方法的調(diào)用耗時,實際開發(fā)中如果你的一個接口經(jīng)過壓測耗時在100ms左右(大多數(shù)正規(guī)公司對接口性能都會要求不超過100ms),那么再通過線程池+Future并行計算的方式,并可以瞬間將你的接口性能提高上去,再也不用擔(dān)心壓測不過了。
有時候測試同學(xué)告訴你接口壓測不過是不是覺得很沒面子?那是對你職業(yè)水平很大的否定~
Java8的CompletableFuture
Future是java.util.concurrent并發(fā)包中的接口類,用來表示一個線程異步執(zhí)行后的結(jié)果,有如下核心方法:
- Future.get():阻塞調(diào)用線程,直到計算結(jié)果返回
- Future.isDone():判斷線程是否執(zhí)行完畢
- Future.cancel():取消當(dāng)前線程的執(zhí)行
我們可以知道的是,F(xiàn)uture.get()是阻塞調(diào)用的,要想拿到線程執(zhí)行的結(jié)果,必須是Future.get()阻塞或者while(Future.isDone())輪詢方式調(diào)用。這種方式叫“主動拉(pull)”,現(xiàn)在都流行響應(yīng)式編程,即“主動推(push)”的方式,當(dāng)線程執(zhí)行完了,你告訴我就好了。
Java8設(shè)計了CompletableFuture這樣的一個類,我們先來看看如何用CompletableFuture來開發(fā)之前的代碼:
CompletableFuture并行計算
這里可以看到實現(xiàn)方式和Future并沒有什么不同,但是CompletableFuture提供了很多方便的方法,比如代碼中的allOf,thenApplyAsync,可以將多個CompletableFuture組合成一個CompletableFuture,最后調(diào)用join方法阻塞拿到結(jié)果。多次調(diào)用該接口耗時如下:
耗時:110ms耗時:108ms耗時:105ms
CompletableFuture類中有很多的方法(50+)可以供大家使用,不像Future只要那么幾個方法可以使用,這也是Java自有庫對Future的一個增強。
這里只是簡單展示了CompletableFuture的一種用法,實際開發(fā)中大家需要根據(jù)不同的場景去選擇使用不同的方法,這里對API不做具體介紹了。
Guava的ListenableFuture
總是有一些牛逼的公司牛逼的人出一些牛逼的開源組件要比官方自帶的工具類要好得多,同樣,谷歌開源的Guava中的ListenableFuture接口對java自帶的Future接口做了進一步拓展,并且提供了靜態(tài)工具類Futures。
針對上面的代碼,我們看如何使用ListenableFuture來實現(xiàn)(與之前不同的是,Guava中需要對線程池再進行一次包裝):
執(zhí)行三次請求耗時:
耗時:103ms耗時:101ms耗時:103ms
最后
以上就是如何讓自己的接口并行計算起來的三種實現(xiàn)方式,屬于日常開發(fā)中比較常用的一個小技巧,這里沒有過多說明這三種方式的具體區(qū)別,實際上還需要大家不斷的在開發(fā)中去使用,查閱更多相關(guān)源碼和資料,只有等你真正用起來的時候,你才能有所體會!
標(biāo)題名稱:你應(yīng)該這樣去開發(fā)接口:Java多線程并行計算
標(biāo)題來源:http://m.fisionsoft.com.cn/article/coiehce.html


咨詢
建站咨詢
