提示:這裏我只是聊聊自己的理解,相當於自己記個筆記而已,如果有誤,請指正。
背景:爲了更加深刻的理解Java,近期比較深入理解線程池。
線程池優勢:線程池做的工作主要是控制運行的線程數量,處理過程中將任務放入隊列然後字線程創建後啓動這些任務,如果數量超過了最大數量,超出數量的線程放到隊列中等候,當其它線程執行完畢,再從隊列中取出任務來執行。簡單來講就是:控制最大併發數,管理線程。
線程池好處:(1)降低資源消耗。通過重複利用已創建的線程降低線程創建和銷燬造成的消耗;(2)提高響應速度。當任務到達時,任務可以不需要等待線程創建就能立即執行;(3)提高線程的可管理。線程是稀缺資,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一分配,調優和監控。
關係圖如下:
創建實例的方式:
public class MyThreadPoolDemo {
public static void main(String[] args) {
//Thread_3menthod();
//現實中 使用這個(自定義)
System.out.println(Runtime.getRuntime().availableProcessors());
ExecutorService threadPool = new ThreadPoolExecutor(2,
5,
2L,
TimeUnit.SECONDS,new LinkedBlockingDeque<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
try {
for (int i=0;i<9;i++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"\t 辦理業務");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.shutdown();
}
}
//這裏是內置的方法,一般情況我們不用他們
private static void Thread_3menthod() {
//一池5個工作線程,相當於一個銀行有5個受理窗口
ExecutorService threadPool = Executors.newFixedThreadPool(5);
//一池1個工作線程,相當於一個銀行有1個受理窗口
ExecutorService threadPool2 = Executors.newSingleThreadExecutor();
//一池n個工作線程,相當於一個銀行有n個受理窗口
ExecutorService threadPool3 = Executors.newCachedThreadPool();
try {
for (int i=0;i<10;i++){
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"\t 辦理業務");
});
//TimeUnit.SECONDS.sleep(1);
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.shutdown();
}
}
}
線程池七大參數理解:
- corePoolSize:線程池中的常駐核心線程數
- maxNumPoolSize:線程池中最多能容納同時執行的最大線程數,此值必須大於等於1
- keeAliveTime:多餘的空閒的線程的存活時間,當前池中線程數量超過corePoolSize時,空閒實際達到keepAliveTime時,多餘線程會被銷燬知道剩下的線程數爲corePoolSize爲止
- unit:keeyAliveTime的單位
- workQueue:任務隊列,被提到尚未執行的任務
- threadFactory:表示生成線程池中工作線程的工廠,用於創建線程,一般用默認Executors.defaultThreadFactory()
即可 - handler:決絕策略,表示隊列慢了,並且工作線程大於等於maxNumPoolSize時如何在拒絕請求執行的runnable的策略(策略可選如下圖)
執行過程如下:
- 在創建了線程池後,開始等待請求;
- 當調用execute()方法添加一個請求任務是,線程池會做出如下判斷:(1)如果正在運行的線程數量小於corePoolSize時,那麼立馬創建線程運行這個任務(2)如果正在運行的線程數量大於或等於corePoolSize,那麼將這個任務放入隊列(3)如果這個時候隊列滿了且正在運行的線程數量還小於maxNumPoolSize,那麼還是要創建費核心線程立刻運行這個任務(4)如果隊列滿了且正在運行的線程數量大於等於maxNumPoolSize,那麼線程池會自動飽和拒絕策略來執行
- 當一個線程完成任務時,它會從隊列中取下一個任務來執行
- 當一個線程無事可做超過keepAliveTime時,線程會判斷,如果當前運行的線程數大於corePoolSize時,那麼這個線程會被停掉
實際中選哪個使用:
根據阿里開發的手冊,線程池不允許使用Executors去創建的,而是通過ThreadExecutor的方式創建。原因:Executors返回的線程池弊端如下:(1)Executors.newFixedThreadPool、Executors.newSingleThreadExecutor、Executors.newScheduledThreadPool和Executors.newCachedThreadPool(),允許的請求隊列長度長度Integer.MAX_VALUE,可能會堆積大量的請求,從而導致OOM。
現總結到這吧!!