線程池是一個在多線程場景中運用很廣泛的并發框架,需要異步執行或并發執行任務的程序都可以使用線程池。有任務到來時,如果不使用線程池,我們需要不斷的創建/銷毀線程,還需要對線程進行管理;而使用線程池,直接將任務提交到線程池即可。使用線程池有幾個好處:無需重復創建/銷毀線程,降低資源消耗;提高程序響應速度;提高線程的可管理性。
## 3.1 實現原理
線程池內部一般包含一個核心線程池,其內部的線程在創建之后一般不會銷毀,執行完任務后線程會阻塞等待新任務到來。
當向線程池提交任務時,線程池會做如下判斷:
* 核心線程池未滿,創建線程執行任務
* 核心線程池已滿,若等待隊列未滿,則加入到等待隊列;若等待隊列已滿但線程池未滿,創建新線程執行任務;若等待隊列和線程池均已滿,則按照指定策略退出/拒絕任務/丟棄任務等。

了解了實現原理,我們先來自己實現一個線程池,首先定義線程池的接口
**ThreadPool**
線程池的接口里面最重要的方法是execute執行任務
```
public interface ThreadPool<Job extends Runnable> {
//提交一個Job,這個Job需要實現Runnable接口
void execute(Job job);
//關閉線程池
void shutdown();
//增加工作者線程
void addWorkers(int num);
//減少工作者線程
void removeWorker(int num);
//得到正在等待執行的任務數量
int getJobSize();
}
```
**CommonThreadPool**
在實現線程池時,我們需要定義線程池的大小,以及保存任務的列表jobs,下面是變量定義:
```
// 線程池最大限制數
private static final int MAX_WORKER_NUMBERS = 100;
// 線程池默認的數量
private static final int DEFAULT_WORKER_NUMBERS = 1;
// 線程池最小數量
private static final int MIN_WORKER_NUMBERS = 1;
// 工作列表
private final LinkedList<Job> jobs = new LinkedList<Job>();
```
在線程池初始化時,我們要將核心線程池進行初始化,創建多個Worker線程,然后啟動Worker線程。
```
// num 為DEFAULT_WORKER_NUMBERS 默認線程池大小
private void initializeWokers(int num) {
// 創建多個線程,加入workers中,并啟動
for (int i = 0; i < num; i++) {
Worker worker = new Worker();
workers.add(worker);
Thread thread = new Thread(worker, "ThreadPool-Worker-"
+ threadNum.getAndIncrement());
thread.start();
}
}
```
Worker啟動后,一直沒有任務,需要阻塞在jobs上(jobs是上面定義的任務列表),Worker等待任務到來后喚醒獲取隊列中的任務并執行。下面的代碼中,如果jobs為空,則線程等待;
```
// worker的代碼,首先要獲取jobs的鎖,
synchronized (jobs) {
while (jobs.isEmpty()) {// 如果jobs是空的,則執行jobs.wait,使用while而不是if,因為wait后可能已經為空了,需要繼續等待
try {
jobs.wait();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();// 中斷
return;// 結束
}
}
job = jobs.removeFirst();// 第一個job
if (job != null) {
try {
job.run();//注意,這里是run而不是start,傳入的Job
} catch (Exception e) {
// 忽略Job執行中的Exception
e.printStackTrace();
}
}
}
```
提交任務時,只需要將任務加入jobs中,然后通知worker線程即可。worker線程獲得鎖后會取第一個任務執行。執行完畢,若jobs為空,worker線程繼續進行休眠等待任務到來。
```
@Override
public void execute(Job job) {
if (job == null)
return;
synchronized (jobs) {
jobs.addLast(job);
jobs.notify();
}
}
```
完整的代碼可以查看https://github.com/ssj234/JavaStudy_IO/tree/master/IOResearch/src/net/ssj/pool