JUC之線程池

一、爲什麼要使用線程池

  1. 降低資源消耗。通過重複利用已創建的線程降低線程創建和銷燬造成的銷耗。
  2. 提高響應速度。當任務到達時,任務可以不需要等待線程創建就能立即執行。
  3. 提高線程的可管理性。線程是稀缺資源,如果無限制的創建,不僅會銷耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,調優和監控。
  4. 線程池的三個特點
  • 線程複用
  • 控制最大併發數
  • 線程管理

二、線程池的使用

Executor類圖

在這裏插入圖片描述

基本使用

參考博文JUC之創建線程的四種方式

三、底層原理

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

三種創建線程池的方式都是通過底層調用ThreadPoolExecutor類來實現的。

ThreadPoolExecutor類的參數解析

  1. int corePoolSize
    線程池中常駐核心線程數。
  2. int maximumPoolSize
    線程池中能夠容納同時執行的最大線程數,大於等於corePoolSize。
  3. long keepAliveTime
    空閒線程的存活時間,超過corePoolSize指定數量的空閒線程,當空閒時間達到keepAliveTime將會被銷燬。
  4. TimeUnit unit
    keepAliveTime的單位。
  5. BlockingQueue workQueue
    任務隊列,被提交但尚未被執行的任務。
    newFixedThreadPool 和 newSingleThreadExecutor默認是LinkedBlockingQueue;
    newCachedThreadPool 默認是 SynchronousQueue
  6. ThreadFactory threadFactory
    用於線程池中創建線程,一般保持默認即可。
  7. RejectedExecutionHandler handler
    拒絕策略,表示當隊列滿了,並且工作線程等於線程池能容納的最大線程數時,如何拒絕新提交的任務請求。
  • AbortPolicy(默認的的拒絕策略)
    直接拋出RejectedExecutionException異常
  • CallerRunsPolicy
    哪個線程(調用execute)提交過來的,就還回去給誰(哪來的回哪去),如果提交的線程shutdown了,就將其丟棄
  • DiscardPolicy
    直接丟棄
  • DiscardOldestPolicy
    等待最久的先丟棄

四、線程池的處理流程

在這裏插入圖片描述

  1. 在創建了線程池後,開始等待請求。
  2. 當調用execute()方法添加一個請求任務時,線程池會做出如下判斷:
  • 如果正在運行的線程數量小於corePoolSize,那麼馬上創建線程運行這個任務;
  • 如果正在運行的線程數量大於或等於corePoolSize,那麼將這個任務放入隊列;
  • 如果這個時候隊列滿了且正在運行的線程數量還小於maximumPoolSize,那麼還是要創建非核心線程立刻運行這個任務;
  • 如果隊列滿了且正在運行的線程數量大於或等於maximumPoolSize,那麼線程池會啓動飽和拒絕策略來執行。
  1. 當一個線程完成任務時,它會從隊列中取下一個任務來執行。
  2. 當一個線程無事可做超過一定的時間(keepAliveTime)時,線程會判斷:
    如果當前運行的線程數大於corePoolSize,那麼這個線程就被停掉。
    所以線程池的所有任務完成後,它最終會收縮到corePoolSize的大小。
發佈了44 篇原創文章 · 獲贊 8 · 訪問量 9194
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章