> ### 線程池的優點
1. 提升性能:它們通常在執行大量異步任務時,由于減少了每個任務的調用開銷,并且它們提供了一種限制和管理資源(包括線程)的方法,使得性能提升明顯;
2. 統計信息:每個ThreadPoolExecutor保持一些基本的統計信息,例如完成的任務數量。
> ### 線程池實現
- Executors提供的幾種線程池:
1. FixedThreadPool:它是一種線程數量固定的線程池,當線程處于空閑狀態時,它們并不會被回收,除非線程池被關閉了。當所有的線程都處于活動狀態時,新任務都會處于等待狀態,直到有線程空閑出來。由于FixedThreadPool只有核心線程并且這些核心線程不會被回收,這意味著它能夠更加快速地響應外界的請求。
```
// 實現方法 規定了核心和最大線程池大小,并使兩者一致,使用無界隊列(LinkedBlockingQuene)。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
```
2. CachedThreadPool:是一種線程數量不定的線程池,它只有非核心線程,并且其最大線程數為Integer.MAX_VALUE。從CachedThreadPool的特性來看,這類線程池比較適合執行大量的耗時較少的任務,當整個線程池都處于閑置狀態時,線程池中的線程都會超時而被停止,這個時候CachedThreadPool之中實際上是沒有任何線程的,它幾乎是不占用任何系統資源的。
```
// 實現方法 核心線程池為0,最大線程池無界,使用無緩存隊列(SynchronousQuene)。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
```
3. ScheduledThreadPool:它的核心線程數是固定的,而非核心線程數是沒有限制的,并且當非核心線程閑置時會被立即回收。只要用于執行定時任務和具有固定周期的重復任務。
```
// 實現方法
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
```
4. SingleThreadExecutor:該線程池內部只有一個核心線程,它確保所有的任務都在同一個線程中按順序執行。SingleThreadExecutor的意義在于統一所有的外界任務到一個線程中,這使得在這些人物之間不需要處理線程同步問題。
```
// 實現方法 規定核心、最大線程池數量都為1,使用無界隊列(LinkedBlockingQuene), 且線程池相關參數不可改變
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));}
```
* 自定義實現線程池:
繼承`ThreadPoolExecutor`并提供一個可以傳入`corePoolSize`、`maxPoolSize`、`watiTime`、`timeUnit`、`blockingDeque`、`threadFactory`、`rejectPolicy`等相關參數的構造器。
```
/**
* @param corePoolSize:核心線程數量
* @param maxPoolSize:最大線程數量
* @param watiTime:空閑線程等待時間
* @param timeUnit:時間單位
* @param blockingDeque:等待隊列
* @param threadFactory:線程工廠
* @param rejectPolicy:拒絕策略
**/
public void createThread(int corePoolSize, int maxPoolSize, long watiTime,
TimeUnit timeUnit, BlockingDeque blockingDeque, ThreadFactory threadFactory,
RejectedExecutionHandler rejectPolicy){
// 生成一個線程池 (同時可以使用其提供的兩個鉤子來定義線程執行前后的代碼)
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, watiTime, timeUnit, blockingDeque, threadFactory, rejectPolicy){
public void beforeExecute(Runnable r, Throwable t){ // 線程執行前
}
public void afterExecute(Runnable r, Throwable t){ // 線程執行后
}
};
// 執行
threadPoolExecutor.execute(new Runnable(){
public void run(){
// 線程執行代碼
}
});
// 關閉線程池 等待所有正在執行及等待隊列的線程執行完畢后關閉
threadPoolExecutor.shutdown();
}
```
> ### 線程池中線程執行順序

```
任務--->核心線程池--->等待線程池--->最大線程池---->拒絕策略
```
1. 任務到核心線程池看是否有少于核心線程數量(corePoolSize)的線程正在運行,如果有,即使其他工作線程處于空閑狀態,也會創建一個新線程來處理該請求。
2. 如果核心線程池全都在工作狀態,查看等待隊列(blockingDeque)是否已經滿了,未滿該線程加入到等待隊列。
3. 如果等待隊列已經滿了,查看最大線程池(maxPoolSize)是否已經滿了,沒有就新建一個線程立刻執行,直到超過最大線程池數量。
4. 如果超出最大線程池了,則執行拒絕策略(RejectedExecutionHandler)。
> ### 等待隊列
- 等待隊列的類型有四種:
1.ArrayBlockingQueue:有邊界的數組阻塞隊列,FIFO(先進先出),當超過邊界時,則執行相應的拒絕策略。
2.LinkedBlockingQuene:無邊界的阻塞隊列,當超過corePoolSize時,會一直創建線程,然后再從隊列中執行任務,相當于maximumPoolSize無效。
3.SynchronousQuene:無緩存隊列,生產者產生一個任務到隊列,必須有一個任務從隊列中被執行,也就是說新的任務進來時,會創建線程來執行,當線程數超過maximumPoolSize時,執行拒絕策略。
4.PriorityBlockingQueue:具有優先級的無邊界隊列,根據參數comparator實現。
> ### 拒絕策略
- ThreadPoolExecutor 靜態內部類提供4種拒絕策略:
1. AbortPolicy 直接報錯
2. CallerRunsPolicy 直接執行Runnable里的run方法,該策略有可能造成主線程的阻塞
3. DiscardPolicy 什么也不做,不報錯,也不執行。
4. DiscardOldestPolicy 最先進入隊列的線程出隊,然后ThreadPoolExecutor再執行該線程。
- 自定義拒絕策略
實現 RejectedExecutionHandler 并重寫其 rejectedExecution(Runnable r, ThreadPoolExecutor e) 方法;
- 2111總結
- 1.面向對象
- 1.0.1 super()與this()的區別
- 1.0.2 private、default、protected、public的訪問范圍
- 1.0.3 continue、break、return區別
- 1.0.4 重載和重寫的區別
- 1.0.5 final的特點
- 1.0.6 抽象類與接口的區別
- 1.0.7 java類型
- 1.0.8 什么是反射
- 1.0.9 類的加載機制
- 1.1.1 jvm內存結構
- 1.1.2 java垃圾回收機制
- 1.1.3 并發問題
- 1.1.3.1 線程的狀態與關系
- 1.1.3.2 并發的三大性質
- 1.1.3.3 線程的實現與使用
- 1.1.3.4 線程池相關
- 1.1.3.5 并發相關方法
- 1.1.3.6 線程相關工具
- 1.1.4 jdk8特性
- 1.1.4.1 lambad表達式的使用
- 1.1.4.2 stream API
- 1.1.4.3 Optional容器使用
- 1.1.4.4 LocalDateTime
- 1.15 io流
- 1.16 動態代理實現
- 2.JavaEE
- 2.0.1 JSP四大作用域九大內置對象
- 2.0.2 cookie與session的區別
- 4.數據庫相關
- 5.git版本管理
- 7.一些問題解決
- 7.1 分布式鎖如何實現