性能優化中,其中一塊是線程池的使用,初探線程池,從簡單瞭解到源碼分析,深入理解才能合理運用。
(一)線程池的來源及優點
單個異步任務,每次都需創建線程、銷燬線程,當任務處理的時間短而請求數卻巨大時,將導致資源消耗過多。
比如,數據庫連接,需消耗大量資源,建立線程池能重用數據庫訪問線程。
使用線程池的優點:
1.降低資源消耗。重用現有線程,減少線程創建銷燬開銷。
2.提高響應速度。任務啓動,無需經歷線程創建,速度提升。
3.線程控制性強。如定時、定期、單線程設置等。
(二)線程池類別
四種線程池類型:
1.newCachedThreadPool
有緩存的線程池,適用於大量短期任務
2.newFixedThreadPool
定長的線程池,可控制最大線程併發數
3.newScheduledThreadPool
定長的線程池,可定時和週期性執行線程
4.newSingleThreadExecutor
單線程的線程池,保證所有任務按順序執行
(三)線程池類別實例分析
1.newCachedThreadPool
private void newCacheThreadPool() {
ExecutorService threadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
final int index = i;
try {
if (i == 1 || i == 3) {
Thread.sleep(100);
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("new cached thread pool " + index + ":" +
Thread.currentThread().getId());
}
});
}
}
運行結果:
new cached thread pool 0:9
new cached thread pool 1:9
new cached thread pool 2:10
new cached thread pool 3:10
new cached thread pool 4:9
例子分析:因爲1和3線程休息了一下,等待其他線程執行完,所以重用了舊有的線程。2.newFixedThreadPool
private void newFixedThreadPool() {
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for (int i = 0; i < 5; i++) {
final int index = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("new fixed thread pool " + index + ":" +
Thread.currentThread().getId());
}
});
}
}
運行結果:
new fixed thread pool 0:9
new fixed thread pool 1:10
new fixed thread pool 2:9
new fixed thread pool 4:9
new fixed thread pool 3:10
例子分析:定長爲2,其他線程進入隊列,等待前倆線程執行完才運行。3.newScheduledThreadPool
private void newScheduledThreadPool() {
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(2);
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
e.printStackTrace();
}
threadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("new scheduled thread pool :" + Thread.currentThread().getId());
}
}, 1, 3, TimeUnit.SECONDS);
}
運行結果:
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
new scheduled thread pool :9
例子分析:延遲1秒開始,每隔3秒運行一次。
4.newSingleThreadExecutor
private void newSingleThreadPool() {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int index = i;
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("new single thread pool " + index + ":" +
Thread.currentThread().getId());
}
});
}
}
運行結果:
new single thread pool 0:9
new single thread pool 1:9
new single thread pool 2:9
new single thread pool 3:9
new single thread pool 4:9
例子分析:只有單線程,所以,每次只能執行一個線程,其餘任務等待狀態。
一般來說,CachedTheadPool在程序執行過程中通常會創建與所需數量相同的線程,然後在它回收舊線程時停止創建新線程,因此它是合理的Executor的首選,只有當這種方式會引發問題時(比如需要大量長時間面向連接的線程時),才需要考慮用FixedThreadPool。(該段話摘自《Thinking in Java》第四版)
線程池源碼分析請看java-線程池(二)