線程池的優點及其原理


一 使用線程池的好處

池化技術應用:線程池、數據庫連接池、http連接池等等。

池化技術的思想主要是為了減少每次獲取資源的消耗,提高對資源的利用率。

線程池提供了一種限制、管理資源的策略。 每個線程池還維護一些基本統計信息,例如已完成任務的數量。

使用線程池的好處:

  • 降低資源消耗:通過重復利用已創建的線程降低線程創建和銷毀造成的消耗。

  • 提高響應速度:當任務到達時,可以不需要等待線程創建就能立即執行。

  • 提高線程的可管理性:線程是稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,監控和調優。

 

二 Executor框架

Executor框架不僅包括了線程池的管理,還提供了線程工廠、隊列以及拒絕策略等,讓並發編程變得更加簡單。

Executor框架的使用示意圖

  1. 主線程首先要創建實現Runnable或Callable接口的任務對象。

  2. 把創建完成的實現Runnable/Callable接口的對象直接交給ExecutorService執行:

    ExecutorService.execute(Runnable command)或者ExecutorService.sumbit(Runnable command)或ExecutorService.sumbit(Callable <T> task).
  3. 如果執行ExecutorService.submit(...),ExecutorService將返回一個實現Future接口的對象。最后,主線程可以執行FutureTask.get()方法來等待任務執行完成。主線程也可以執行FutureTask.cancel()來取消次任務的執行。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorDemo {

    private static final int CORE_POOL_SIZE = 5;
    private static final int MAX_POOL_SIZE = 10;
    private static final int QUEUE_CAPACITY = 100;
    private static final Long KEEP_ALIVE_TIME = 1L;

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());

        //執行線程代碼

        executor.shutdown();

    }

}
 

CORE_POOL_SIZE:核心線程數定義了最小可以同時運行的線程數量。

MAX_POOL_SIZE:當隊列中存放的任務到達隊列容量的時候,當前可以同時運行的線程數量變為最大線程數。

QUEUE_CAPACITY:當新任務加入是會先判斷當前運行的線程數量是否達到核心線程數,如果達到的話,任務就會被存放到隊列中。

KEEP_ALIVE_TIME:當線程池中的線程數量大於核心線程數時,如果這時沒有新的任務提交,核心線程外的線程不會立即銷毀,而是會等待,直到等待的時間超過KEEP_ALIVE_TIME才會被回收銷毀。

ThreadPoolExecutor.CallerRunsPolicy():調用執行自己的線程運行任務,也就是直接在調用execute方法的線程運行(run)被拒絕的任務,如果執行程序已關閉,則會丟棄任務。因此這種策略會降低新任務的提交速度,影響程序的整體性能。另外,這個策略喜歡增加隊列容量。如果應用程序可以承受此延遲並且不能任務丟棄一個任務請求的話,可以選擇這個策略。

 

線程池分析原理

 

三 線程池大小確定

有一個簡單且使用面比較廣的公式:

  • CPU密集型任務(N+1):這種任務消耗的主要是CPU資源,可以將線程數設置為N(CPU核心數)+1,比CPU核心數多出來一個線程是為了防止線程偶發的缺頁中斷,或者其他原因導致的任務暫停而帶來的影響。一旦任務停止,CPU就會出於空閑狀態,而這種情況下多出來一個線程就可以充分利用CPU的空閑時間。

  • I/O密集型(2N):這種任務應用起來,系統大部分時間用來處理I/O交互,而線程在處理I/O的是時間段內不會占用CPU來處理,這時就可以將CPU交出給其他線程使用。因此在I/O密集型任務的應用中,可以配置多一些線程,具體計算方是2N。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM