該篇主要介紹Excecutor相關(guān)實(shí)現(xiàn)類(lèi)的用法烙常。
Executor相關(guān)類(lèi)圖
Executor接口:里面只提供了一個(gè)方法 void execute(Runnable command);執(zhí)行一個(gè)Runnable線程
ExecutorService:提供Executor的管理(提交废亭,停止運(yùn)行)及查詢(xún),以及新增了invokeAll,invokeAny方法具钥。
AbstractExecutorService:對(duì)ExecutorService的部分實(shí)現(xiàn)豆村,以及新增了newTaskFor方法,該方法主要對(duì)Runnable以及Callable進(jìn)行封裝返回RunnableFuture骂删。方便對(duì)submit方法提及的任務(wù)結(jié)果進(jìn)行統(tǒng)一獲取掌动。
invokeAll方法實(shí)現(xiàn)如下
首先遍歷集合內(nèi)所有Callable,調(diào)用newTaskFor方法將返回結(jié)果放入ArrayList中宁玫,并執(zhí)行task;
然后對(duì)list中task進(jìn)行遍歷獲取每個(gè)task的結(jié)果粗恢;
最后finally對(duì)通過(guò)集合內(nèi)所有任務(wù)執(zhí)行完成與否進(jìn)行判斷,如果出現(xiàn)異撑繁瘢或者運(yùn)行期間被取消眷射,則對(duì)所有任務(wù)執(zhí)行cancel操作。
超時(shí)方法邏輯總體沒(méi)有變化佛掖,只是在執(zhí)行任務(wù)期間添加了超時(shí)判斷
1.在對(duì)list遍歷期間妖碉,如果超時(shí)則直接返回futures,需要注意的是,此時(shí)可能并非左右任務(wù)都被execute.也就是說(shuō)只是在單位時(shí)間內(nèi)盡可能多的執(zhí)行任務(wù)芥被,并不保證所有任務(wù)都被執(zhí)行欧宜。
2.在所有任務(wù)都執(zhí)行后通過(guò)遍歷futures進(jìn)行Future.get方法是加了超時(shí)參數(shù)。
由圖可知invokeAny方法最終是通過(guò)內(nèi)部方法doInvokeAny執(zhí)行的
通過(guò)代碼可以看出該方法多出一個(gè)ExecutorCompletionService類(lèi)撕彤,任務(wù)也是通過(guò)該類(lèi)來(lái)進(jìn)行提交鱼鸠。該類(lèi)的主要作用是將執(zhí)行的任務(wù)結(jié)果放入queue中方便進(jìn)行獲取。
總體流程如下:
1.首先在將tasks任務(wù)集合中的一個(gè)任務(wù)進(jìn)行ecs.submit并放入futures集合中羹铅,激活任務(wù)數(shù)active=1
2.通過(guò)死循環(huán)獲取第一個(gè)執(zhí)行完的任務(wù)
? ? ? ? a.首先通過(guò)ecs.poll查看第一個(gè)提交的任務(wù)是否執(zhí)行完畢
????????b.當(dāng)f == null時(shí)蚀狰,首先判斷ntasks>0如果是,則增加一個(gè)新任務(wù)執(zhí)行职员,并更新ntasks和avtive,如果否,說(shuō)明所有任務(wù)都正在運(yùn)行麻蹋,然后進(jìn)行其他判斷,當(dāng)active==0時(shí)焊切,說(shuō)明所有任務(wù)都執(zhí)行異常直接break,然后拋出異常信息扮授;否則判斷是否有執(zhí)行超時(shí)時(shí)間限制,如果有則信息超時(shí)獲取任務(wù)結(jié)果专肪。當(dāng)超時(shí)未獲取到執(zhí)行結(jié)果時(shí)拋出超時(shí)異常刹勃;否則則阻塞等待執(zhí)行結(jié)果;
? ? ? ? ?c.如果執(zhí)行f != null,則說(shuō)明執(zhí)行完畢嚎尤,--active,進(jìn)行f.get()獲取荔仁,正常情況下獲取成功,跳出循環(huán),當(dāng)獲取異常時(shí)進(jìn)行異常賦值并執(zhí)行下一輪輪循環(huán)乏梁。
? ? ? ? d.finally中對(duì)所有任務(wù)進(jìn)行取消
可以看出獲取最先執(zhí)行完的結(jié)果主要通過(guò)ExecutorCompletionService對(duì)task進(jìn)行包裝執(zhí)行次洼,下面查看該類(lèi)是如何包裝的
通過(guò)代碼看出該類(lèi)對(duì)所有提交的task進(jìn)行包裝為QueueingFuture任務(wù)執(zhí)行,QueueingFuture繼承FutureTask并對(duì)其中的done方法進(jìn)行了實(shí)現(xiàn)遇骑,將任務(wù)的結(jié)果放入BlockingQueue中卖毁。這就是為什么可以從隊(duì)列中獲取到任務(wù)執(zhí)行結(jié)果的原因。也是invokeAny的核心思想所在落萎『ダ玻看完以后只能說(shuō)構(gòu)思巧妙,只能說(shuō)大師的代碼結(jié)構(gòu)真牛皮模暗。