爲何要使用線程池?java
1.頻繁的建立、銷燬線程伴隨着系統開銷,會在很大程度上影響系統性能,效率會下降;併發
2.線程併發數量過大的狀況下,線程直接搶佔資源會致使系統阻塞;函數
3.線程池會對線程進行一些簡單的管理。性能
實現學習
在java中管理線程的是java.util.concurrent包下的Executor接口。這個接口的具體實現類是ThreadPoolExecutor類。學習線程的話,主要是對這個類的構造函數進行一些配置。spa
ThreadPoolExecutor的構造函數線程
構造函數參數的不一樣又分爲四個構造函數(有5個參數的,6個參數的,7個參數的),後面會具體講解,請往下看。對象
構造函數中各個參數的意義接口
1.隊列
int corePoolSize 該線程池中核心線程的數的最大值,線程池在新建線程的時候,若是當前的線程總數小於corePoolSize,則新建的是核心線程。
2.
int maximumPoolSize 該線程池中線程總數的最大值,線程總數=核心線程數+非核心線城數。
3.
long keepAliveTime 該線程池中非核心線城閉置狀態下起始時長,一個非核心線城,若是閉置狀態下的時長超過這個參數設定的時長,就會被銷燬。
4.
TimeUnit unit 就是一個枚舉類型
5.
BlockingQueue<Runnable> workQueue 2該線程池中的任務隊列,維護着等待的對象,當全部的核心線城都在幹活時,新添加的任務會到這個隊列中等待被處理,若是隊列滿了,就會建立非核心線程執行任務。
6.
ThreadFactory threadFactory 建立線程的方式,這是一個接口
7.
RejectedExecutionHandler handler 拋異常專用,若是有錯誤產生,則由handler拋出
經常使用的4種線程池(根據業務場景選擇)
1. CachedThreadPool()
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
根據源碼能夠看出這種線程池是沒有核心線程的,在建立任務時,如有空閒的線程則複用,不然就建立一個新的線程,沒有工做的線程,超過60s就會被銷燬。
2.FixedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
經過源碼能夠看出該線程池的最大線程數等於核心線程數,因此該線程池的的線程不會由於閉置狀態起時被銷燬。若是當前線程數小於核心線程,不會去複用以前的線程,會建立新的線程去執行任務;若是當前執行任務大於該線程的核心線程數,大於的任務會在隊列中等待。
3.SingleThreadPool()
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
僅有一個工做線程執行任務,全部的任務遵循隊列的入隊出隊規則
4.SchdeledThreadPool()
public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory, handler); }
設置了最大線程數,核心線程數。這個線程是惟一一個有延遲執行和週期執行任務的線程池。