線程池產生背景:高併發項目中常常須要同時啓用大量線程,所以須要建立大量線程,而頻繁的建立新線程和殺死舊線程將會大大拖慢CPU的性能,所以利用線程池一次性初始化若干線程,使用時從池中彈出線程,執行完線程池再予以回收java
線程池的工做流程:主要是控制運行的線程數量,處理過程當中將任務放入隊列,而後在線程建立後啓動這些任務,若是線程數量超過了最大數量,超出數量的線程排隊等候,等其餘線程執行完畢,再從隊列中取出任務執行編程
線程池的主要特色:實現線程複用、控制最大併發數;可以系統地管理線程併發
線程池的優點:ide
// 源碼 public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable\>()); }
// 源碼 public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable\>())); }
// 源碼 public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX\_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable\>()); }
實質上,這三種線程池雖然各有特色,但底層實現的都是ThreadPoolExecutor類,也即最正統的線程池,線程池本池☺高併發
// 使用案例 import java.util.concurrent.Executors; public class NewFixedThreadPoolDemo { public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(5); // ExecutorService threadPool = Executors.newSingleThreadExecutor(); // ExecutorService threadPool = Executors.newCachedThreadExecutor(); for(int i=0; i<10; i++){ threadPool.execute(()-> System.out.println(Thread.currentThread().getName() + "\t 辦理業務")); } threadPool.shutdown(); // 關閉資源!! } }
// 代碼實現 import java.util.concurrent.*; public class ThreadPoolExecutorDemo { public static void main(String[] args) { ExecutorService threadPool = new ThreadPoolExecutor(2, 5, 2L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.DiscardPolicy()); for(int i=1; i<=10; i++){ final int temp = i; threadPool.execute(()-> System.out.println(Thread.currentThread().getName() + "\t辦理業務" + temp)); } threadPool.shutdown(); } }
talk is cheap, show me the diagram工具
線程池通常時間都只會開啓核心線程數量的線程,而當任務隊列滿了以後,線程池會啓用非核心線程池區(這裏描述只是邏輯分區,實際上線程之間都是同等地位),建立線程並執行任務;而當任務隊列中任務變少,有些線程開始閒置,閒置時間達到設置的keepAliveTime後,線程池會註銷回收這些閒置線程,直到線程數量恢復核心線程數性能
共有四種拒絕策略,以2.2中的代碼爲準,即設置核心線程數爲二、最大線程數爲五、任務隊列容量爲三、任務數爲10;見四種策略分別的運行結果以下spa