線程池(ThreadPoolExecutor)重要參數解析

ThreadPoolExecutor線程池繼承ExecutorService,用來解決2個問題:

  • 執行大量異步任務的時候,通過每個線程一個任務的方法,減少線程調用開銷,提升性能;
  • 設置線程池最大線程數,管理線程資源的調用。執行大量任務的時候會不斷消耗線程;

常見的三種線程池:

  • newCachedThreadPool
    • 優點:任何需要的時候都會創建新線程執行任務,當有可用的空閒線程(空閒線程在60秒內如果沒有使用,會將該線程終止)時會優先使用可用線程,除非無可用線程;可以運用於執行大量運行時間短的任務;
    • 缺點:不適合運行時間長的任務,因爲會佔着CPU資源,導致CPU性能降低;有可能會在短時間內創建大量線程執行任務;
  • newFixedThreadPool
    • 優點:corePoolSize和maximumPoolSize相同,只會產生一定數量的線程,如果線程都在使用,會優先將任務放在隊列中等待,並不會再產生新的線程。適合執行運行時間較長的任務;
    • 缺點:如果線程池使用率不高,會導致大量空閒的線程,佔用CPU資源。產生大量的空閒線程的原因,是因爲此種線程池的keepAliveTime設置爲0,也就是空閒線程永遠不會被終止。反之,如果大量長時間運行任務佔用了所有線程,那麼其他任務要加入線程池,只能在無邊界隊列中等待,又會導致佔着大量內存。
    • 特點:不允許線程池動態擴展核心線程數(因爲maximumPoolSize被設置爲等於corePoolSize),任意線程在線程池關閉前發生了異常導致該線程異常終止,會創建新的線程替代該線程。
  • newSingleThreadExecutor
    •           優點:corePoolSize和maximumPoolSize相同,並且只會產生一個線程執行任務。
    •           缺點:如果當前線程被一個長時間運行任務佔用,那麼新的任務只能加入無界隊列中等待,導致佔用大量內存,而且影響其他任務的執行效率。
    •           特點:只有一個線程執行任務,如果在線程池關閉前發生了異常導致線程異常終止,會創建新的線程替代失敗的線程;任務按順序執行;

重要參數:

corePoolSize:核心線程數,核心線程不會被終止。除非allowCoreThreadTimeOut設置爲true;

maximumPoolSize:最大核心線程數,超過keepAliveTime時間的線程,將被終止;

keepAliveTime:線程允許空閒最大時間,不能小於0。如果設置該參數,線程空閒時間超過keepAliveTime後,將被終止,終止的線程範圍爲:corePoolSize<可能終止線程<= maximumPoolSize;

allowCoreThreadTimeOut:允許空閒核心線程超時終止,如果設置爲true,則核心線程空閒時間超過keepAliveTime後,仍將被終止。

workQueue:任務等待隊列,放入隊列需遵循以下3個原則:

  1. 當線程池中的工作線程少於corePoolSize時,線程池優先爲新任務創建線程;
  2. 當線程池中需要的線程大於corePoolSize時,線程池優先將新任務放入隊列中等待;
  3. 當隊列已經放滿,線程池將會創建新的線程執行任務,直到線程數量等於maximumPoolSize。如果需要的線程大於maximumPoolSize,線程池將會拒絕接收。

handler:拒絕策略,以下2種情況會執行拒絕策略:

  1. 當線程池已經關閉,提交新任務時會拒絕;
  2. 當線程池設置了明確的maximumPoolSize和workQueue的最大值,並且線程池已經飽和,提交新任務會拒絕;

4種已知拒絕策略:

1,ThreadPoolExecutor.AbortPolicy,默認拒絕策略,拒絕策略會拋出RejectedExecutionException異常;

2,ThreadPoolExecutor.CallerRunsPolicy,使用此種策略,在執行execute方法時,會使用當前線程立即執行新任務,調用Runnable的run方法而不經過線程池執行;

3,ThreadPoolExecutor.DisgardPolicy,使用此種策略,會忽視新任務,產生的效果就是,新提交任務將被丟棄;

4,ThreadPoolExecutor.DisgardOldestPolicy,使用此種策略,會首先將workQueue中的Head元素丟棄,並且嘗試執行新任務,一直循環直到該任務被線程池接收。如果該線程池關閉,新任務將被丟棄;

開發人員可以定製自己的拒絕策略,但是在處理時需要特別小心。

線程池所有狀態解釋:

 

重要方法:

execute():提交併執行任務,執行邏輯:

                      1,當線程池中線程數少於corePoolSize,創建新線程執行任務;

                      2,當大於corePoolSize,放入等待隊列中;

                      3,當隊列中已經放滿,創建新線程執行任務,直到線程池線程數=maximumPoolSize。否則拒絕接收任務,並執行拒絕策略;

 

           shutdown():關閉線程池,只執行等待隊列中的任務(但是不會等待所有任務執行完畢),不接收新任務並且終止空閒線程。 如果已經關閉但是再次執行shutdown,沒有任何作用。注意:shutdown()只會執行等待隊列中的任務,但是不會等待所有任務執行完畢才關閉,意味着,此時仍然有線程在運行任務,如果要等待所有運行任務關閉,可以調用awaitTermination()方法;

           shutdownNow():關閉線程池,不接收新任務,不執行等待隊列中的任務,所有任務將被丟棄,並打斷所有在運行中的任務,而且會返回所有未執行的任務(估計是讓使用方自己決定是否後續用來執行未完成的任務)。注意:shutdownNow()不會等待所有任務執行完畢才關閉,意味着,此時仍然有線程在運行任務,如果要等待所有運行任務關閉,可以調用awaitTermination()方法;

           awaitTermination(long timeout, TimeUnit unit):先加鎖,判斷線程池是否關閉,如果已關閉,返回true;反之,會將當前線程置於等待狀態(等待時間爲方法入參,調用方控制)並將當前鎖釋放。如果等待超時,當前線程將重新激活,並繼續判斷線程池是否關閉,關閉返回true,  否則判斷剩餘等待時間是否小於0,小於0返回false。

          想來想去,awaiTermination可以這麼用,先調用shutdownNow(),此時也許線程池還有任務在運行。那再調用awaitTermination(),確保線程池所有的任務都已終止,一次不夠那麼就再調用一次。

 

            如有不正確的地方,請指正,共同進步,某將感激不盡!

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章