Java併發之線程池簡介

一、線程池簡介    

    在Java中,使用線程來異步執行任務。Java線程的創建與銷燬需要一定的開銷,如果我們爲每個任務創建一個新的線程來執行,這些線程的創建與銷燬將消耗大量的計算資源。Java的線程在此情況下,既是工作單元,也是執行機制。爲了減少創建線程的額外開支,將工作單元與執行機制分離不失爲一個好辦法。由此,Java線程池自然的被設計出了。

    合理地使用線程池帶來極大的好處:

    1)降低資源消耗:通過重複利用已創建的線程降低線程創建和銷燬帶來的開銷。

    2)提高響應速度:當任務到達時,任務可以不需要等待線程創建就能立刻執行。

    3)提高線程的可管理性:線程是稀缺資源,如果無限制地創建,不僅會消耗資源,而且會降低系統的穩定性,使用線程池可以進行統一分配、調優和監控。

    但是,要充分發揮線程池的優點,就必須掌握其使用方法和適用條件,對其實現原理也必須瞭如指掌。下面我們主要介紹線程池的主要實現類ThreadPoolExecutor。

二、線程池的狀態

    ThreadPoolExecutor中一共有5種狀態。分別是:

  • RUNNING:接受新的任務並且處理阻塞隊列中的任務。
  •  SHUTDOWN:拒絕新的任務,但是會將阻塞隊列中的任務完成。
  • STOP:拒絕新的任務,拋棄阻塞隊列中的任務,中斷正在處理的任務。
  •  TIDYING:所有任務都已經執行完成,線程池中活動線程爲0,阻塞隊列也爲空,此時將要調用 terminated()方法。
  •  TERMINATED:執行完terminated()方法,線程池處於終止狀態。

三、線程池狀態轉換

  •    RUNNING=》SHUTDOWN
            顯示調用shutdown()方法,或者隱式調用finalize(),它裏面調用了shutdown()方法。
  • RUNNING or SHUTDOWN =》STOP
            顯式調用shutdownNow()方法。
  • SHUTDOWN =》 TIDYING
            當線程池和阻塞隊列都爲空時。
  • STOP=》TIDYING
            當線程池爲空是。
  • TIDYING=》TERMINATED
            當terminated()的hook方法執行完成時。

四、線程池參數

  • corePoolSize:線程池核心線程個數
  • workQueue:阻塞隊列,用於保存等待執行的任務。
  • maximumPoolSize:線程池最大線程數量
  • threadFactory:創建線程的工廠
  • RejectedExecutionHandler:飽和策略,當隊列滿了並且活動線程數達到maximumPoolSize時採取的策略。
  • keepAliveTime:存活時間,當活動線程數大於核心線程數並且處於閒置狀態,這些閒置線程能存活的最大時間。
  • TimeUnit:存活時間單位。

五、線程池主要處理流程

    當向線程池提交一個任務之後,線程池的主要處理流程如圖:
  1. 判斷核心線程池裏面線程是否已滿。如果未滿,則創建新的工作線程執行任務。如果已滿,則進入下個流程。
  2. 判斷工作隊列是否滿了。如果未滿,則加入工作隊列。如果滿了,進入下個流程。
  3. 判斷線程池線程數有沒有達到最大線程數。如果滿了,採取飽和策略。如果未滿,創建線程執行任務。
    之所以採取上述的設計思路,是因爲1、3創建新線程需要獲取全局鎖,開銷很大。在ThreadPoolExecutor預熱之後,絕大部分execute()方法調用都是執行第二步,而這時不需要全局鎖的。

六、RejectedExecutionHandler策略

    當隊列和線程池都滿了,必須採取一種策略處理提交的新任務。默認是AbortPolicy。java 1.5中提供了四種策略:
  • AbortPolicy:直接拋出異常。
  • CallerRunsPolicy:只用調用者線程來運行。
  • DiscardOldestPolicy:丟棄隊列裏最近的一個任務,並執行當前任務。
  • DiscardPolicy:不處理,直接丟棄。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章