Executor家族一覽

筆記來自於Java多線程編程實戰指南編程

此次沒有用MD來寫筆記,可能排版有點難受安全


Runnable / Callable 接口是對任務處理邏輯的抽象,也就是說無論怎樣的處理邏輯,均有同一的簽名方法:run/call,而不關心具體的處理邏輯多線程

Exectuor接口是對任務的執行進行的抽象:也就是說任務提交方(生產者)只需知道execute可以使指定的任務被執行,不關心具體的執行細節(好比是由工做者進程仍是怎樣的線程池來執行)異步

接口僅定義了 void execute(Runnable command)線程

抽象的好處:
1.提交與執行解耦
2.信息隱藏/關注點分離,就是OOP中的封裝
3.屏蔽同步執行和異步執行的差別,提交到ThreadPoolExecutor就是異步執行,自行implement接口直接在execute中調用run就是同步執行對象

Executor缺點:
1.只能爲客戶端代碼執行任務,沒法將任務結果返回
2.實現類須要維護一些工做者線程,當再也不須要該Executor實例時,須要主動釋放資源繼承

所以做爲改進新增ExecutorService接口(其默認實現是ThreadPoolExecutor)
1.提供submit接受Callable和Runnable並返回Future實例
2.提供shutdown和shutdownNow來關閉相應服務(如關閉維護的工做者線程), PS.shutdownNow內部調用Interrupt方法來實現接口

util類Executors大概功能一覽
1.提供一些好用的ExecutorService線程池實例,如newCachedThreadPool/newFixedThreadPool/newSingleThreadPool(後者沒法轉換hreadPoolExecutor實例)
2.提供Runnable轉換Callable實例
3.返回默認線程工廠defaultThreadFactory隊列

線程池調優選擇
Executors給出的各類線程池實例其實是調用
new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAlive,timeUnit,blockingQueue,threadFactory,rejectExecutionHandler)(夠長吧
其中keepAlive和timeUnit用於指定空閒時間,僅負責處理超過核心大小的部分
線程池任務存入工做隊列是調用非阻塞的offer(e)
handler用於超過線程池閾值時的處理,該RejectExecutionHandler接口僅定義單一的方法:rejectExecution(runnable,threadPoolExecutor),也有幫你搞定的util實現類:
AbortPolicy(異常)/DiscardPolicy(丟棄當前)/DiscardOldestPolicy(丟棄queue中最老的任務,從新嘗試)/CallerRunsPolicy(客戶端Caller線程執行)進程

newCachedThreadPool適用於大量耗時短且提交頻繁的任務(耗時過長會致使線程過多而上下文切換頻繁),隊列使用SynchronousQueue
newFixedThreadPool核心線程池大小=最大線程池大小keepAlive=0(空閒不清理),隊列使用LinkedBlockingQueue
newSingleThreadPool適用於單/多生產者但消費者模式,也可用於執行非線程安全對象(不肯意爲此加鎖)

PS.線程池實例可接受ThreadFactory參數,可用於標準化線程的生產流程(統一配置),好比書中P316的XThreadFactory爲線程所作的大概有
1.關聯UncaughtExceptionHandler
2.確保用戶線程/線程名稱含義/優先級..
3.更友好的toString

CompletionService用於一次性批量提交異步任務,暫略

題外話:關於Future和FutureTask

Future接口實例可認爲是任務處理結果句柄,大概有那麼多定義的方法
1.get()會阻塞以得到執行結果(須要處理InterruptedException和ExecutionException),所以有一個原則是儘可能早的submit,儘可能晚的get
2.cancel(mayInterrupted)
3.isDone()/isCancelled()/get(time,unit)
也就是說Future使得獲知任務的不僅是結果(Callable返回的V),還有當前任務的執行狀況,不過要處理的異常蠻多的...(還沒寫全
注意判斷完成的狀況比較複雜

Runnable優勢:可交給簡單的工做者線程/Executor的execute/線程池的submit(關於submit須要後面補充)
Runnable缺點:沒法得知結果

Callable優勢:能得知結果
Callable缺點:只能遞交給線程池執行

注意點:Runnable做爲executorService的參數時也是能夠返回Future的,但源碼實現中(具體看AbstractExecutorService的實現)是調用newTaskFor(你可認爲就是用了callable轉換方法)直接給null做爲結果(返回的具體是RunnableFuture,下面會說它是啥)...

FutureTask是Future接口的惟一實現類,它直接實現自RunnableFuture接口 (而RunnableFuture繼承自Runnable和Future,可做爲二者使用) 其目的就是要結合Runnable和Callable的優勢,具體地,就是你實現了Callable示例,直接用它來構造出FutureTask便能轉換成Runnable實例,由多態確保能遞交給簡單的工做者線程/Executor的execute/線程池的submit(具體看源碼吧,提及來真繞) 除此之外,FutureTask還能擁有Future的特色,既得到結果(Callable的結果經過get獲得而不會由於"轉換"成Runnable而丟失),而且能擁有此前提到的關於Future得到任務執行情況和取消的方法 其實類的名字已經說清楚了,既是Future,也是Task

相關文章
相關標籤/搜索