天天看點

線程池參數解析以及送出任務的流程

線程池參數解析以及送出任務的流程

  • ​​線程池的 6 個參數​​
  • ​​線程池處理新送出的任務​​
線程池參數解析以及送出任務的流程

線程池的好處

  • 降低資源消耗:通過重複利用已建立的線程降低線程建立和銷毀造成的消耗。
  • 提高響應速度:當任務到達時,任務可以不需要等到線程建立就能立即執行。
  • 提高線程的可管理性:線程是稀缺資源,如果無限制地建立,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一配置設定、調優和監控。

線程池的 6 個參數

線程池參數解析以及送出任務的流程

ThreadPoolExecutor(Executor 接口的實作類)提供的構造方法:

ThreadPoolExecutor有以下四個構造方法

  • ​ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)​

  • ​ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, -BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)​

  • ​ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)​

  • ​ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)​

1 ​

​corePoolSize​

​(線程池的基本大小):當送出一個任務到線程池時,線程池會建立一個線程來執行任務,即使其他空閑的基本線程能夠執行新任務也會建立線程,等到需要執行的任務數大于線程池基本大小時就不再建立。如果調用了prestartAllCoreThreads()方法,線程池會提前建立并啟動所有基本線程。

2 ​

​workQueue(任務隊列)​

​ : 用于儲存等待執行的任務的阻塞隊列。可以選擇以下幾個阻塞隊列:

  • ArrayBlockingQueue:是一個基于數組結構的有界阻塞隊列,按FIFO原則進行排序
  • LinkedBlockingQueue:一個基于連結清單結構的阻塞隊列,吞吐量高于ArrayBlockingQueue。靜态工廠方法Excutors.newFixedThreadPool()使用了這個隊列
  • SynchronousQueue: 一個不存儲元素的阻塞隊列。每個插入操作必須等到另一個線程調用移除操作,否則插入操作一直處于阻塞狀态,吞吐量高于LinkedBlockingQueue,靜态工廠方法Excutors.newCachedThreadPool()使用了這個隊列
  • PriorityBlockingQueue:一個具有優先級的無限阻塞隊列。

    3 ​​

    ​maximumPoolSize(線程池最大數量)​

    ​​:線程池允許建立的最大線程數。如果隊列滿了,并且已建立的線程數小于最大線程數,則線程池會再建立新的線程執行任務。值得注意的是,如果使用了無界的任務隊列這個參數就沒用了。

    4 ​​

    ​threadFactory(線程工廠)​

    ​​:可以通過線程工廠為每個建立出來的線程設定更有意義的名字,如開源架構guava

    5 ​​

    ​RejectedExecutionHandler (飽和政策)​

    ​:當隊列和線程池都滿了,說明線程池處于飽和狀态,那麼必須采取一種政策還處理新送出的任務。它可以有如下四個選項:
  • AbortPolicy:直接抛出異常,預設情況下采用這種政策
  • CallerRunsPolicy:隻用調用者所線上程來運作任務
  • DiscardOldestPolicy:丢棄隊列裡最近的一個任務,并執行目前任務
  • DiscardPolicy:不處理,丢棄掉

    更多的時候,我們應該通過實作RejectedExecutionHandler 接口來自定義政策,比如記錄日志或持久化存儲等。

    6​​

    ​keepAliveTime(線程活動時間)​

    ​:線程池的工作線程空閑後,保持存活的時間。是以如果任務很多,并且每個任務執行的時間比較短,可以調大時間,提高線程使用率。

7 ​

​TimeUnit(線程活動時間的機關)​

​:可選的機關有天(Days)、小時(HOURS)、分鐘(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和納秒(NANOSECONDS,千分之一微秒)。

線程池處理新送出的任務

當一個任務送出到線程池,線程池的處理流程:

線程池參數解析以及送出任務的流程

總結:任務進來之後,線程池會逐一判斷 corePoolSize 、workQueue 、maxPoolSize ,如果依然不能滿足需求,則會拒絕任務。

有兩種方法向線程池送出任務:

可以使用execute和submit兩個方法向線程池送出任務

  1. ​execute方法用于送出不需要傳回值的任務,利用這種方式送出的任務無法得知是否正常執行​

threadPoolExecutor.execute(new Runnable() {
      
      @Override
      public void run() {
        try {
          Thread.sleep(5000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    });      
Future<?> future=threadPoolExecutor.submit(futureTask);
    
    Object value=future.get();      

關閉線程池的方法:

繼續閱讀