Java中線程池的拋出策略、阻塞隊列、內存溢出


   Java中官方推薦的線程池有四種:線程池介紹參考:https://www.cnblogs.com/CarpenterLee/p/9558026.html;在jdk1.8加入了 ForkJoinPool的擴展,newWorkStrealingPool,能夠合理的使用CPU對任務進行並行操作,適合用於耗時的操作

   但是這幾種線程池會造成OOM的問題;

        1、阻塞隊列是無界的,導致不停的往隊列中加任務,最后導致溢出;

       2、啟用的線程數量 過多,例如newCachedThreadPool ,這種線程池的maxmumPoolSize是max_Integer 所以如果當前線程數大於core並且隊列已滿的情況下,就會創建新線程,如果aliveTime時間較長沒有及時GC掉,最終導致溢出;

       

   所以一般推薦使用  new ThreadPoolExecutor(int corePoolSize,int maxNumPoolSize,long keepAliveTime,TimeUnit,BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler policy)來進行自定義線程池;在這里先重點梳理一下線程池中的阻塞隊列和拒絕策略:

 阻塞隊列有:

      基於數組結構的: ArrayBlockingQueue  :創建時要指定一個容量;

     基於鏈表結構的:  LinkedBlockingQueue、LinkedBlockingDeque 創建時可以指定容量,不指定則默認為一個無界隊列;newFixedThreadPool、newSingleThreadPool、用的是這個無界的Queue

     同步的: SynchronousQueue:容量為0,這種同步隊列只有在有線程寫入元素時,另一個線程才能通過poll獲取到元素,否則返回null;簡單來說這種隊列將任務直接提交,而不維持隊列,在自定義線程池中默認的隊列;newCachedThreadPool用的是這個

     混合的:DelayedWorkQueue:基於DelayQueue和PriorityQueue,是延遲的並且具有自然排序的阻塞隊列;newScheduledThreadPool用這個。

                  PriorityBlockingQueue: 一個支持優先級排序的無界阻塞隊列,對元素沒有要求,可以實現Comparable接口也可以提供Comparator來對隊列中的元素進行比較,跟時間沒有任何關系,僅僅是按照優先級取任務。

 

拒絕策略:

作用場景:在隊列已滿,並且線程數量達到了maxmumPoolSize的時候;

拒絕策略的接口是: RejectedExecutionHandler;ThreadPoolExecutor中提供了四個靜態方法返回實現了該接口的對象:

    AbortPolicy:拋出RejectedExecutionException異常

    CallerRunsPolicy:直接由提交任務者來執行這個任務(一般是main線程);因此使用這種策略會導致主線程堵塞;容易導致故障

    DiscardOldesPolicy:彈出隊列中最年長的任務,嘗試將要執行的任務加到隊列中;

   DiscardPolicy:忽略這個任務,不拋出異常

        

附一張很好的線程池工作流程圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM