一.Executors創建線程執行器的基本方式及其弊端
1.四種創建執行器方法的簡介
java創建線程執行器(Executor接口實現類)時常用以下代碼
//合理的首選:CachedThreadPool會在程序執行的時候創建與需要同等數量的線程,回收九線城市停止創建新線程;
ExecutorService executorService= Executors.newCachedThreadPool();
//同名,應該與“定時”相關
ExecutorService executorService=Executors.newScheduledThreadPool(5);
//創建固定數量的線程集處理提交的任務,不用付出創建每個任務的開銷。
ExecutorService executorService=Executors.newFixedThreadPool(5);
//類似於線程數量爲1的FixThreadPool,若提交了多個任務則人物會排隊,即SingleThreadExecutor會序列化其處理的任務。
ExecutorService executorService=Executors.newSingleThreadExecutor();
2.Executors方法創建執行器的弊端
阿里java編程規範並不允許直接用Executors去創建,因爲Executors中的newXXXThreadPool()方法實現方式是返回Executor接口實現類,經常是ThreadPoolExecutor或其子類ScheduledThreadPoolExecutor。由於其構造參數是java源碼指定,靈活性並不高。
阿里Java編程規範建議使用更細粒度的ThreadPoolExecutor或者ScheduledThreadPoolExecutor去創建線程執行器,這樣可以熟悉線程執行器對象創建時的參數細節,規避資源浪費。圖1展示了線程池接口Executor及實現類的繼承關係:
如圖所示。籃圈中使我們一般使用的引用接口類型,大概是因爲除了其實現的接口Executor,他還有許多方法可供調用,比如void shutdown()來結束執行器對象接受新的任務。兩個實現類ThreadPoolExecutor、ScheduledThreadPoolExecutor是阿里推薦的實現執行器的最小粒度元素。
newFixedThreadPool和newSingleThreadExecutor堆積的請求處理隊列可能耗費非常大的內存,甚至OOM(out of memory:內存溢出)。方法源碼如下,注意各有其同名重載的實現:
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),//這個參數
threadFactory);
}
public static ExecutorService newSingleThreadExecutor() {
return new Executors.FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));//最後這個參數
}
newCacheThreadPool和newScheduledThreadPool方法線程最大數是Integer.MAX_VALUE,可能創建非常多的線程,設置造成內存溢出。方法源碼如下,注意各有其同名重載的實現:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
二.創建執行器ExecutorService
…待更新