天天看點

淺析線程池 ---Java并發程式設計的藝術(八)線程池線程池的實作原理

線程池

  • 線程池
  • 線程池的實作原理
    • 飽和政策
    • 幾個核心參數
    • java中提供的線程池
    • execute()和submit()方法

線程池

Java中的線程池是運用場景最多的并發架構,幾乎所有需要異步或并發執行任務的程式都可以使用線程池

什麼是線程池

線程池是一種多線程處理形式,處理過程中将任務添加到隊列,然後在建立線程後自動啟動這些任務。線程池線程都是背景線程。

為什麼要使用線程池

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

線程池的實作原理

線程池是如何處理任務的呢?

1)線程池判斷核心線程池裡的線程是否都在執行任務。如果不是,則建立一個新的工作線程來執行任務。如果核心線程池裡的線程都在執行任務,則進入下個流程。

2)線程池判斷工作隊列是否已經滿。如果工作隊列沒有滿,則将新送出的任務存儲在這個工作隊列裡。如果工作隊列滿了,則進入下個流程。

3)線程池判斷線程池的線程是否都處于工作狀态。如果沒有,則建立一個新的工作線程來執行任務。如果已經滿了,則交給飽和政策來處理這個任務。

淺析線程池 ---Java并發程式設計的藝術(八)線程池線程池的實作原理

如果看不懂,可以看下面這個圖

淺析線程池 ---Java并發程式設計的藝術(八)線程池線程池的實作原理

飽和政策

RejectedExecutionHandler(飽和政策):當隊列和線程池都滿了,說明線程池處于飽和狀态,那麼必須采取一種政策處理送出的新任務。這個政策預設情況下是AbortPolicy,表示無法處理新任務時抛出異常

  • AbortPolicy:直接抛出異常。
  • CallerRunsPolicy:隻用調用者所線上程來運作任務
  • DiscardOldestPolicy:丢棄隊列裡最近的一個任務,并執行目前任務。
  • DiscardPolicy:不處理,丢棄掉

幾個核心參數

  • corePoolSize corePoolSize(線程池的基本大小):當送出一個任務到線程池時,線程池會建立一個線程來執行任務,即使其他空閑的基本線程能夠執行新任務也會建立線程,等到需要執行的任務數大于線程池基本大小時就不再建立。如果調用了線程池的prestartAllCoreThreads()方法,線程池會提前建立并啟動所有基本線程。
  • runnableTaskQueue (任務隊列):用于儲存等待執行的任務的阻塞隊列。可以選擇以下幾

    個阻塞隊列。

    • ArrayBlockingQueue:是一個基于數組結構的有界阻塞隊列,此隊列按FIFO(先進先出)原

      則對元素進行排序

    • LinkedBlockingQueue:一個基于連結清單結構的阻塞隊列,此隊列按FIFO排序元素,吞吐量通

      常要高于ArrayBlockingQueue。靜态工廠方法Executors.newFixedThreadPool()使用了這個隊列。

    • SynchronousQueue:一個不存儲元素的阻塞隊列。每個插入操作必須等到另一個線程調用

      移除操作,否則插入操作一直處于阻塞狀态,吞吐量通常要高于Linked-BlockingQueue,靜态工

      廠方法Executors.newCachedThreadPool使用了這個隊列

    • ·PriorityBlockingQueue:一個具有優先級的無限阻塞隊列。
  • keepAliveTime(線程活動保持時間) 線程池的工作線程空閑後,保持存活的時間。是以,如果任務很多,并且每個任務執行的時間比較短,可以調大時間,提高線程的使用率。
  • TimeUnit(線程活動保持時間的機關) 可選的機關有天(DAYS)、小時(HOURS)、分鐘(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和納秒(NANOSECONDS,千分之一微秒)。

java中提供的線程池

Executors類提供了4種不同的線程池:

1、newCachedThreadPool:用來建立一個可以無限擴大的線程池,适用于負載較輕的場景,執行短期異步任務。(可以使得任務快速得到執行,因為任務時間執行短,可以很快結束,也不會造成cpu過度切換)

2、newFixedThreadPool:建立一個固定大小的線程池,因為采用無界的阻塞隊列,是以實際線程數量永遠不會變化,适用于負載較重的場景,對目前線程數量進行限制。(保證線程數可控,不會造成線程過多,導緻系統負載更為嚴重)

3、newSingleThreadExecutor:建立一個單線程的線程池,适用于需要保證順序執行各個任務。

4、newScheduledThreadPool:适用于執行延時或者周期性任務。

execute()和submit()方法

1、execute(),執行一個任務,沒有傳回值。

2、submit(),送出一個線程任務,有傳回值。

前幾天就看完了,一值懶得總結,今天晚上加加班,寫完前幾天複習完的,加油加油!