本文轉載自https://blog.csdn.net/kusedexingfu/article/details/72491864
Java提供了4鍾線程池:
newCachedThreadPool
newFixedThreadPool
newSingleThreadExecutor
newScheduledThreadPool
你可以通過Executors來實例化這四種線程池。
查看源碼會發現,這四種線程池都直接或者間接獲取的ThreadPoolExecutor實例 ,只是實例化時傳遞的參數不一樣。所以如果java提供的四種線程池滿足不了我們的需求,我們可以創建自定義線程池。
ThreadPoolExecutor的構造方法如下:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactor threadFactory, RejectdExecutionHandler handler)
其中:
corePoolSize: 核心池的大小。 當有任務來之后,就會創建一個線程去執行任務,當線程池中的線程數目達到corePoolSize后,就會把到達的任務放到緩存隊列當中
maximumPoolSize: 線程池最大線程數,它表示在線程池中最多能創建多少個線程;
keepAliveTime: 表示線程沒有任務執行時最多保持多久時間會終止。
unit: 參數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性:
-
TimeUnit.DAYS; //天
-
TimeUnit.HOURS; //小時
-
TimeUnit.MINUTES; //分鍾
-
TimeUnit.SECONDS; //秒
-
TimeUnit.MILLISECONDS; //毫秒
-
TimeUnit.MICROSECONDS; //微妙
TimeUnit.NANOSECONDS;
//納秒
workQueue: 一個阻塞隊列,用來存儲等待執行的任務。 一般來說,這里的阻塞隊列有以下幾種選擇:
ArrayBlockingQueue;
LinkedBlockingQueue;
SynchronousQueue
threadFactory: 線程工廠,主要用來創建線程;
handler: 表示當拒絕處理任務時的策略,有以下四種取值:
ThreadPoolExecutor.AbortPolicy:丟棄任務並拋出RejectedExecutionException異常。
ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。
ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程)
ThreadPoolExecutor.CallerRunsPolicy:只要線程池不關閉,該策略直接在調用者線程中,運行當前被丟棄的任務
個人認為這4中策略不友好,最好自己定義拒絕策略,實現RejectedExecutionHandler接口
handler: 表示當拒絕處理任務時的策略,有以下四種取值:
ThreadPoolExecutor.AbortPolicy:丟棄任務並拋出RejectedExecutionException異常。
ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。
ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程)
ThreadPoolExecutor.CallerRunsPolicy:只要線程池不關閉,該策略直接在調用者線程中,運行當前被丟棄的任務
個人認為這4中策略不友好,最好自己定義拒絕策略,實現RejectedExecutionHandler接口
以下主要講解存儲等待執行的任務的隊列對線程池執行的影響。
以下主要講解存儲等待執行的任務的隊列對線程池執行的影響。
一.有界隊列
1.初始的poolSize < corePoolSize,提交的runnable任務,會直接做為new一個Thread的參數,立馬執行 。
2.當提交的任務數超過了corePoolSize,會將當前的runable提交到一個block queue中,。
3.有界隊列滿了之后,如果poolSize < maximumPoolsize時,會嘗試new 一個Thread的進行救急處理,立馬執行對應的runnable任務。
4.如果3中也無法處理了,就會走到第四步執行reject操作。
public class ThreadPoolExcutorTest implements Runnable { public String name; public ThreadPoolExcutorTest(String name) { this.name = name; } @Override public void run() { System.out.println(name); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(3); ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 1, //corePoolSize 2, //maximumPoolSize 1L, TimeUnit.SECONDS, workQueue ); threadPool.execute(new ThreadPoolExcutorTest("任務1")); threadPool.execute(new ThreadPoolExcutorTest("任務2")); threadPool.execute(new ThreadPoolExcutorTest("任務3")); threadPool.execute(new ThreadPoolExcutorTest("任務4")); threadPool.execute(new ThreadPoolExcutorTest("任務5")); threadPool.execute(new ThreadPoolExcutorTest("任務6")); threadPool.shutdown(); } }
執行結果是:

二.無界隊列
與有界隊列相比,除非系統資源耗盡,否則無界的任務隊列不存在任務入隊失敗的情況。當有新的任務到來,系統的線程數小於corePoolSize時,則新建線程執行任務。當達到corePoolSize后,就不會繼續增加,若后續仍有新的任務加入,而沒有空閑的線程資源,則任務直接進入隊列等待。若任務創建和處理的速度差異很大,無界隊列會保持快速增長,直到耗盡系統內存。public class ThreadPoolExcutorTest2 implements Runnable { public Integer count; public ThreadPoolExcutorTest2(Integer count) { this.count= count; } @Override public void run() { System.out.println("任務" + count); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(); ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 1L, TimeUnit.SECONDS, workQueue); for (int i = 1; i <= 20; i++) { pool.execute(new ThreadPoolExcutorTest2(i)); } Thread.sleep(1000); System.out.println("線程池中隊列中的線程數量:" + workQueue.size()); pool.shutdown(); } }
如果修改了線程池的maximumPoolSize參數(大於corePoolSize的大小),程序執行結果不受影響。所以對於無界隊列,maximumPoolSize的設置設置的再大對於線程的執行是沒有影響的。
Ps:這里說LinkedBlockingQueue是無界隊列是不恰當的,只不過如果用無參構造函數初始化,默認的容量是Integer.MAX_VALUE
當線程池的任務緩存隊列已滿並且線程池中的線程數目達到maximumPoolSize,如果還有任務到來就會采取任務拒絕策略。
總結:
可以用以下一句總結:當線程池的任務緩存隊列已滿並且線程池中的線程數目達到maximumPoolSize,如果還有任務到來就會采取任務拒絕策略。