Executor 与 ExecutorService 和 Executors 傻傻分不清
轉(zhuǎn)載自??Executor 與 ExecutorService 和 Executors 傻傻分不清
java.util.concurrent.Executor, java.util.concurrent.ExecutorService, java.util.concurrent. Executors 這三者均是 Java Executor 框架的一部分,用來提供線程池的功能。因為創(chuàng)建和管理線程非常心累,并且操作系統(tǒng)通常對線程數(shù)有限制,所以建議使用線程池來并發(fā)執(zhí)行任務(wù),而不是每次請求進來時創(chuàng)建一個線程。使用線程池不僅可以提高應用的響應時間,還可以避免”java.lang.OutOfMemoryError: unable to create new native thread” 之類的錯誤。
在 Java 1.5 時,開發(fā)者需要關(guān)心線程池的創(chuàng)建和管理,但在 Java 1.5 之后 Executor 框架提供了多種內(nèi)置的線程池,例如:FixedThreadPool(包含固定數(shù)目的線程),CachedThreadPool(可根據(jù)需要創(chuàng)建新的線程)等等。
Executor
Executor, ExecutorService, 和 Executors 最主要的區(qū)別是 Executor 是一個抽象層面的核心接口(大致代碼如下)。
public?interface?Executor?{void?execute(Runnable?command); }不同于 java.lang.Thread 類將任務(wù)和執(zhí)行耦合在一起, Executor 將任務(wù)本身和執(zhí)行任務(wù)分離,可以閱讀 difference between Thread and Executor 來了解 Thread 和 Executor 間更多的不同。
ExecutorService
ExecutorService 接口 對 Executor 接口進行了擴展,提供了返回 Future 對象,終止,關(guān)閉線程池等方法。當調(diào)用 shutDown 方法時,線程池會停止接受新的任務(wù),但會完成正在 pending 中的任務(wù)。
Future 對象提供了異步執(zhí)行,這意味著無需等待任務(wù)執(zhí)行的完成,只要提交需要執(zhí)行的任務(wù),然后在需要時檢查 Future 是否已經(jīng)有了結(jié)果,如果任務(wù)已經(jīng)執(zhí)行完成,就可以通過 Future.get() 方法獲得執(zhí)行結(jié)果。需要注意的是,Future.get() 方法是一個阻塞式的方法,如果調(diào)用時任務(wù)還沒有完成,會等待直到任務(wù)執(zhí)行結(jié)束。
通過 ExecutorService.submit() 方法返回的 Future 對象,還可以取消任務(wù)的執(zhí)行。Future 提供了 cancel() 方法用來取消執(zhí)行 pending 中的任務(wù)。
ExecutorService 部分代碼如下:
public?interface?ExecutorService?extends?Executor?{void?shutdown();<T>?Future<T>?submit(Callable<T>?task);<T>?Future<T>?submit(Runnable?task,?T?result);<T>?List<Future<T>>?invokeAll(Collection<??extends?Callable<T>>?tasks,?long?timeout,?TimeUnit?unit)?throws?InterruptedException; }Executors
Executors 是一個工具類,類似于 Collections。提供工廠方法來創(chuàng)建不同類型的線程池,比如 FixedThreadPool 或 CachedThreadPool。
Executors 部分代碼:
public?class?Executors?{public?static?ExecutorService?newFixedThreadPool(int?nThreads)?{return?new?ThreadPoolExecutor(nThreads,?nThreads,?0L,?TimeUnit.MILLISECONDS,new?LinkedBlockingQueue<Runnable>());}public?static?ExecutorService?newCachedThreadPool()?{return?new?ThreadPoolExecutor(0,?Integer.MAX_VALUE,?60L,?TimeUnit.SECONDS,?new?SynchronousQueue<Runnable>());} }下面詳細看一下三者的區(qū)別。
Executor vs ExecutorService vs Executors
正如上面所說,這三者均是 Executor 框架中的一部分。Java 開發(fā)者很有必要學習和理解他們,以便更高效的使用 Java 提供的不同類型的線程池。總結(jié)一下這三者間的區(qū)別,以便大家更好的理解:
-
Executor 和 ExecutorService 這兩個接口主要的區(qū)別是:ExecutorService 接口繼承了 Executor 接口,是 Executor 的子接口。
-
Executor 和 ExecutorService 第二個區(qū)別是:Executor 接口定義了 execute()方法用來接收一個Runnable接口的對象,而 ExecutorService 接口中的 submit()方法可以接受Runnable和Callable接口的對象。
-
Executor 和 ExecutorService 接口第三個區(qū)別是 Executor 中的 execute() 方法不返回任何結(jié)果,而 ExecutorService 中的 submit()方法可以通過一個 Future 對象返回運算結(jié)果。
-
Executor 和 ExecutorService 接口第四個區(qū)別是除了允許客戶端提交一個任務(wù),ExecutorService 還提供用來控制線程池的方法。比如:調(diào)用 shutDown() 方法終止線程池。可以通過 《Java Concurrency in Practice》 一書了解更多關(guān)于關(guān)閉線程池和如何處理 pending 的任務(wù)的知識。
-
Executors 類提供工廠方法用來創(chuàng)建不同類型的線程池。比如: newSingleThreadExecutor() 創(chuàng)建一個只有一個線程的線程池,newFixedThreadPool(int numOfThreads)來創(chuàng)建固定線程數(shù)的線程池,newCachedThreadPool()可以根據(jù)需要創(chuàng)建新的線程,但如果已有線程是空閑的會重用已有線程。
總結(jié)
下表列出了 Executor 和 ExecutorService 的區(qū)別:
?
譯者注
個人覺得,利用 Executors 類提供的工廠方法來創(chuàng)建一個線程池是很方便,但對于需要根據(jù)實際情況自定義線程池某些參數(shù)的場景,就不太適用了。
舉個例子:
當線程池中的線程均處于工作狀態(tài),并且線程數(shù)已達線程池允許的最大線程數(shù)時,就會采取指定的飽和策略來處理新提交的任務(wù)。總共有四種策略:
-
AbortPolicy: 直接拋異常
-
CallerRunsPolicy: 用調(diào)用者的線程來運行任務(wù)
-
DiscardOldestPolicy: 丟棄線程隊列里最近的一個任務(wù),執(zhí)行新提交的任務(wù)
-
DiscardPolicy 直接將新任務(wù)丟棄
如果使用 Executors 的工廠方法創(chuàng)建的線程池,那么飽和策略都是采用默認的 AbortPolicy,所以如果我們想當線程池已滿的情況,使用調(diào)用者的線程來運行任務(wù),就要自己創(chuàng)建線程池,指定想要的飽和策略,而不是使用 Executors 了。
所以我們可以根據(jù)需要創(chuàng)建 ThreadPoolExecutor(ExecutorService接口的實現(xiàn)類) 對象,自定義一些參數(shù),而不是調(diào)用 Executors 的工廠方法創(chuàng)建。
當然,在使用 Spring 框架的項目中,也可以使用 Spring 提供的 ThreadPoolTaskExecutor 類來創(chuàng)建線程池。ThreadPoolTaskExecutor 與 ThreadPoolExecutor 類似,也提供了許多參數(shù)用來自定義線程池,比如:核心線程池大小,線程池最大數(shù)量,飽和策略,線程活動保持時間等等。
翻譯:Giraffe
譯文鏈接:http://www.importnew.com/24923.html
總結(jié)
以上是生活随笔為你收集整理的Executor 与 ExecutorService 和 Executors 傻傻分不清的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 毛尖茶产于 了解毛尖茶的主要产地
- 下一篇: json-lib的字符串自动转换坑