Java ThreadPool的正確打開方式

jopen 10年前發布 | 9K 次閱讀 Java開發 ThreadPool

線程池應對于突然增大、來不及處理的請求,無非兩種應對方式:

  1. 將未完成的請求放在隊列里等待
  2. 臨時增加處理線程,等高峰回落后再結束臨時線程
  3. </ol>

    JDK的Executors.newFixedPool() 和newCachedPool(),分別使用了這兩種方式。

    不過,這倆函數在方便之余,也屏蔽了ThreadPool原本多樣的配置,對一些不求甚解的碼農來說,就錯過了一些更適合自己項目的選擇。

     

    1. ThreadPoolExecutor的原理

    經典書《Java Concurrency in Pratice(Java并發編程實戰)》第8章,濃縮如下:

    1. 每次提交任務時,如果線程數還沒達到coreSize就創建新線程并綁定該任務。
    所以第coreSize次提交任務后線程總數必達到coreSize,不會重用之前的空閑線程。

    2. 線程數達到coreSize后,新增的任務就放到工作隊列里,而線程池里的線程則努力的使用take()從工作隊列里拉活來干。

    3. 如果隊列是個有界隊列,又如果線程池里的線程不能及時將任務取走,工作隊列可能會滿掉,插入任務就會失敗,此時線程池就會緊急的再創建新的臨時線程來補救。

    4. 臨時線程使用poll(keepAliveTime,timeUnit)來從工作隊列拉活,如果時候到了仍然兩手空空沒拉到活,表明它太閑了,就會被解雇掉。

    5. 如果core線程數+臨時線程數 >maxSize,則不能再創建新的臨時線程了,轉頭執行RejectExecutionHanlder。默認的AbortPolicy拋 RejectedExecutionException異常,其他選擇包括靜默放棄當前任務(Discard),放棄工作隊列里最老的任務 (DisacardOldest),或由主線程來直接執行(CallerRuns),或你自己發揮想象力寫的一個。

     

    2. FixedPool 與 CachedPool

    FixedPool默認用了一條無界的工作隊列 LinkedBlockingQueue, 所以只去到上面的第2步就不會繼續往下走了,coreSize的線程做不完的任務不斷堆積到無限長的Queue中,所以只有coreSize一個參數,其他maxSize,keepAliveTime,RejectHandler的配置都不會實際生效

    CachedPool則把coreSize設成0,然后選用了一種特殊的Queue --SynchronousQueue,只要當前沒有空閑線程,Queue就會立刻報插入失敗,讓線程池增加新的臨時線程,默認 KeepAliveTime是1分鐘,而且maxSize是整形的最大值,也就是說只要有干不完的活,都會無限增增加線程數,直到高峰過去線程數才會回落。

     

    3. 對FixedPool的進一步配置

    3.1 設置QueueSize
    如果不想搞一條無限長的Queue,避免任務無限等待顯得像假死,同時占用太多內存,可能會把它換成一條有界的ArrayBlockingQueue,那就要同時關注一下這條隊列滿了之后的場景,選擇正確的rejectHanlder。

    此時,最好還是把maxSize設為coreSize一樣的值,不把臨時線程及其keepAlive時間拉進來,Queue+臨時線程兩者結合聽是好聽,但很難設置好。

     

    4. 對CachedPool的進一步配置

    4.1 設置coreSize

    coreSize默認為0,但很多時候也希望是一個類似FixedPool的固定值,能處理大部分的情況,不要有太多加加減減的波動,等待和消耗的精力。

    4.2 設置maxSize及rejectHandler

    同理,maxSize默認是整形最大值,但太多的線程也很可能讓系統崩潰,所以建議還是設一下maxSize和rejectHandler。

    4.3 設置keepAliveTime

    默認1分鐘,可以根據項目再設置一把。

     

    5. SpringSide的ThreadPoolBuilder

    廣告時間,SpringSide的ThreadPoolBuilder能簡化上述的配置。

    此文太科普,不是為了幫SpringSide里的Utils打廣告也不會寫 :)

    </div> 來自:http://calvin1978.blogcn.com/articles/java-threadpool.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!