歡迎來到狗哥多線程系列連載。這篇簡單聊聊線程池的阻塞隊列。java
如圖所示,線程池的內部結構主要由線程池管理器、工做線程、任務隊列以及任務四部分組成。編程
先上張圖,表格左側是線程池,右側爲它們對應的阻塞隊列,你能夠看到 5 種線程池對應了 3 種阻塞隊列。微信
下面逐一說下它們的特色:數據結構
阿里巴巴 Java 規約也約定了,手動建立線程池,效果會更好。爲何呢?回答這個問題以前,先來看看五種線程池初始化的方法:多線程
// FixedThreadPool public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0 L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue < Runnable > ()); } // SingleThreadExecutor public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0 L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue < Runnable > ())); }
首先是 FixedThreadPool 和 SingleThreadExecutor,它兩的問題在於都是用默認容量的無界隊列 LinkedBlockingQueue,當任務處理慢時,隊列迅速積壓任務並佔用大量內存,發生 OOM(內存溢出)。因此在使用時咱們能夠根據業務指定隊列長度:併發
ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 1 L, TimeUnit.SECONDS, new LinkedBlockingQueue < > (3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
而後是 CachedThreadPool,也能夠發現一個問題:它默認的最大線程是 Integer.MAX_VALUE,當任務賊多時,它就會不斷建立線程,而線程執行比較耗時來不及回收。最終也會形成 OOM,因此應該手動指定最大線程數。spa
// CachedThreadPool public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60 L, TimeUnit.SECONDS, new SynchronousQueue < Runnable > ()); }
最後是 ScheduledThreadPool 和 ScheduledThreadPoolExecutor,這兩問題就更大了。首先最大線程數是 Integer.MAX_VALUE,而後阻塞隊列是 DelayedWorkQueue,它也是無界隊列,最終仍是會形成 OOM。線程
// ScheduledThreadPool public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } // ScheduledThreadPoolExecutor public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
若是看到這裏,喜歡這篇文章的話,請幫點個好看。微信搜索一個優秀的廢人,關注後回覆電子書送你 100+ 本編程電子書 ,不僅 Java 哦,詳情看下圖。回覆 1024送你一套完整的 java 視頻教程。code