Java 線程池

線程池

線程池解決了兩個不同的問題:

  1. 減少線程創建的開銷,能提高執行大量異步任務的效率
  2. 提供了一種限制和管理資源及線程的方法,並且還維護了一些基本的統計信息(如已完成的任務數)

線程池的使用對new Thread()的優勢:

  1. 複用存在的線程,減少對象創建、消亡的開銷,性能佳。
  2. 可有效控制最大併發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
  3. 提供定時執行、定期執行、單線程、併發數控制等功能。

ThreadPoolExecutor

常用默認實現:

  1. Executors#newCachedThreadPool:無邊界線程池,帶有自動線程回收
  2. Executors#newFixedThreadPool:固定大小的線程池
  3. Executors#newSingleThreadExecutor:單個後臺線程,大多數場景用於預初始化配置

有需要執行的任務進入線程池時

  • 當前線程數小於核心線程數時,創建線程。
  • 當前線程數大於等於核心線程數,且工作隊列未滿時,將任務放入工作隊列。
  • 當前線程數大於等於核心線程數,且工作隊列已滿
    • 若線程數小於最大線程數,創建線程
    • 若線程數等於最大線程數,拋出異常,拒絕任務(具體處理方式取決於handler的策略)

主要參數

  • corePoolSize
    核心線程數。空閒時仍會保留在池中的線程數,除非設置了allowCoreThreadTimeOut參數

  • maximumPoolSize
    最大線程數。允許在池中的最大線程數

  • keepAliveTime
    存活時間。當前線程數大於核心線程數時,空餘線程的最長存活時間

  • unit
    單位。keepAliveTime參數的時間單位

  • workQueue
    工作隊列,接口類爲阻塞隊列。任務執行前存儲的隊列,只有通過submit方法提交的任務纔會進入隊列

  • threadFactory
    線程工廠。創建線程。默認使用Executors.defaultThreadFactory(),所有的線程都屬於同一個ThreadGroup,都有相同的優先級,且均不是守護線程。
    (可用new NamedThreadFactory("test")來對線程池中的線程添加前綴標識)

  • handler
    任務丟棄策略。若線程池已經關閉、或線程池已滿,那麼新的任務會被拒絕。

    • ThreadPoolExecutor.AbortPolicy:丟棄任務並拋出RejectedExecutionException異常
    • ThreadPoolExecutor.DiscardPolicy:丟棄任務,但不拋出異常。
    • ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然後重新嘗試執行任務(循環此過程)
    • ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務

BlockingQueue

BlockingQueue類型

  • ArrayBlockingQueue:由數組結構組成的有界阻塞隊列
  • LinkedBlockingQueue:由鏈表結構組成的有界阻塞隊列
  • PriorityBlockingQueue:支持優先級排序的無界阻塞隊列
  • DealyQueue:使用優先級隊列實現的無界阻塞隊列
  • SynchronousQueue:不存儲元素的阻塞隊列
  • LinkedTransferQueue:由鏈表結構組成的無界阻塞隊列
  • LinkedBlockingDeque:由鏈表結構組成的雙向阻塞隊列

ArrayBlockingQueue

ArrayBlockingQueue是定長阻塞隊列。原理是使用一個可重入鎖和Condition進行併發控制(classic two-condition algorithm)。


參考資料:

  1. 精通ThreadPoolExcutor
  2. Java併發編程中四種線程池
發佈了109 篇原創文章 · 獲贊 97 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章