为什么阿里巴巴Java开发手册中不允许用Executors去创建线程池?
在我閱讀阿里巴巴開發手冊的時候,有一段關于多線程的描述:
線程池不允許使用 Executors 去創建,而是通過 ThreadPoolExecutor 的方式,這樣 的處理方式讓寫的同學更加明確線程池的運行規則,規避資源耗盡的風險。 說明: Executors 返回的線程池對象的弊端如下: FixedThreadPool 和 SingleThreadPool : 允許的請求隊列長度為 Integer.MAX_VALUE ,可能會堆積大量的請求,從而導致 OOM 。 CachedThreadPool 和 ScheduledThreadPool : 允許的創建線程數量為 Integer.MAX_VALUE ,可能會創建大量的線程,從而導致 OOM 。
當看到不允許使用Executors創建線程池的時候,我有點懵,仔細一看不無道理。
我們來逐個分析。
FixedThreadPool 和 SingleThreadPool
這兩個線程池是線程池大小是固定的。SingleThreadPool是單個線程的線程池。FixedThreadPool在應對平穩流量的時候,能有效的處理,缺點就是可能無法應付突發性大流量。
使用Executors創建:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);我們點開方法看一下:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }兩個方法,都通過了 LinkedBlockingQueue<Runnable>來接收來不及處理的任務。關鍵點就在這個隊列里,默認的構造器容量是Integer.MAX_VALUE。
public LinkedBlockingQueue() {this(Integer.MAX_VALUE);}那就是說,當流量突然變得非常大時,線程池滿,等候隊列變得非常龐大,內存和CPU都告急,這樣無疑對服務器造成非常大的壓力。
CachedThreadPool 和 ScheduledThreadPool
ExecutorService cacheThreadPool = Executors.newCachedThreadPool(); public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());} ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10); public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {return new ScheduledThreadPoolExecutor(corePoolSize);} public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue());}同理,從工廠方法可以看到,這兩種線程池,線程池大小是不固定的,雖然newScheduledThreadPool傳如一個線程數,但是這個數字只是核心線程數,可能還會擴容,直至Integer.MAX_VALUE。而他們使用的隊列是SynchronousQueue和DelayedWorkQueue。這兩個隊列我沒有細看,但初始化時不會像LinkedBlockingQueue那樣一下子將容量調整到最大。
總結:阿里手冊希望程序員們根據業務情況,通過ThreadPoolExecutor手動地去創建線程池,線程池大小應該有個邊界,并選取合適的隊列存儲任務。
總結
以上是生活随笔為你收集整理的为什么阿里巴巴Java开发手册中不允许用Executors去创建线程池?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java线程池示例:任务窃取线程池Wor
- 下一篇: Java线程池:ThreadPoolEx