線程複用:線程池

線程複用:線程池

爲了避免系統頻繁地創建和銷燬線程,我們可以讓創建的線程進行復用。線程池中,總有幾個活躍線程。當你需要使用線程時,可以從池中隨便獲取一個空閒線程,當工作完成時,線程不會關閉而是退回池中。

  • JDK 提供的線程池工廠方法

    • newFixedThreadPool

      返回固定線程數量的線程池。

      當有一個新的任務提交時,線程池若有空閒線程,則立即執行。若沒有,則新的任務會被暫存到一個任務隊列中,待線程空閒時,便處理在任務隊列中的任務。

    • newSingleThreadExecutor

      返回只有一個線程的線程池。

      若多餘一個任務被提及,則保存到任務隊列中,線程空閒時按照先入先出的順序執行任務。

    • newCachedThreadPool

      返回一個可根據實際情況調整線程數量的線程池。

      線程池的線程數量不確定,但若有空閒線程可以複用,則會有限使用可複用的線程。若所有線程均在工作,又有新任務提交,則創建新的線程處理任務。當所有線程在任務執行完之後,將返回線程池進行復用。

    • newSingleThreadScheduledExecutor

      返回一個 ScheduledExecutorService 對象,線程池大小爲1。

      ScheduledExecutorService 接口在 ExecutorService 接口之上擴展了給定時間執行某任務的功能。

    • newScheduledThreadPool

      返回指定線程數量的 ScheduledExecutorService 對象。

  • 線程池的內部實現

    JDK 提供的線程池工廠方法實質就是 ThreadPoolExecutor 的不同參數的不同實現

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

    corePoolSize : 指定線程池中的線程數量。

    maximumPoolSize :指定線程池中的最大線程數量。

    keepAliveTime :超過corePoolSize的空閒線程,在多長時間內,會被銷燬。

    unit :keepAliveTime的單位。

    workQueue :提交但未執行的任務隊列。

    • 直接提交的隊列

      該功能由 SynchronousQueue 對象提供,提交的任務不會被保存,而是直接提交給線程執行,如果沒有空閒的線程,則嘗試創建新的線程,如果已達到最大值則執行拒絕策略。

    • 有界的任務隊列

      ArrayblockingQueue 實現, ArrayblockingQueue 的構造函數需要帶一個容量參數(隊列最大容量)。當有新的任務時,如果線程池實際線程數小於 corePoolSize ,則優先創新新的線程,如果大於 corePoolSize ,則將任務加入等待隊列。

      若等待隊列已滿,則在總線程數不大於 maximumPoolSize 的前提下創建新的線程執行任務,否則則執行拒絕策略。因爲需要等待隊列滿纔會創建超出 corePoolSize 的線程,所以除非系統特別繁忙,否則核心線程數一般維持在 corePoolSize

    • 無界的任務隊列

      LinkedBlockingQueue 實現,和有界的任務隊列類似,只是等待隊列會一直擴張,如果任務的創建速度一直高於處理速度,則無界隊列會一直增長,直至耗盡內存。

    • 優先任務隊列

      PriorityBlockingQueue 實現,是一個特殊的無界隊列,會按照任務自身的優先級順序先後執行。

    threadFactory :線程工廠,用於創建線程,一般默認。

    handler :拒絕策略。當任務太多時如何拒絕任務。

    • AbortPolicy 策略

      直接拋出異常,阻止系統正常工作。

    • CallerRunsPolicy 策略

      只要線程池未關閉,該策略直接在調用者線程中,運行當前被丟棄的任務。這樣做不會真的丟棄任務,但是任務提交的線程性能可能會急劇下降。

    • DiscardPolicy 策略

      丟棄最老的一個請求(即將被執行的下一個任務),並嘗試再次提交當前任務。

    • DiscardOldestPolicy 策略

      直接丟棄無法處理的任務,不做任何處理。

  • 線程池的數量

    Ncpu = CPU數量

    Ucup = CPU的使用率

    W/C = 等待時間與計算時間的比率

    最優池: Nthreads=Ncpu*Ncpu*(1+W/C)

發佈了95 篇原創文章 · 獲贊 32 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章