java高級應用:線程池全面解析

什麼是線程池?

很簡單,簡單看名字就知道是裝有線程的池子,咱們能夠把要執行的多線程交給線程池來處理,和鏈接池的概念同樣,經過維護必定數量的線程池來達到多個線程的複用。java

線程池的好處

咱們知道不用線程池的話,每一個線程都要經過new Thread(xxRunnable).start()的方式來建立並運行一個線程,線程少的話這不會是問題,而真實環境可能會開啓多個線程讓系統和程序達到最佳效率,當線程數達到必定數量就會耗盡系統的CPU和內存資源,也會形成GC頻繁收集和停頓,由於每次建立和銷燬一個線程都是要消耗系統資源的,若是爲每一個任務都建立線程這無疑是一個很大的性能瓶頸。因此,線程池中的線程複用極大節省了系統資源,當線程一段時間再也不有任務處理時它也會自動銷燬,而不會長駐內存。面試

線程池核心類

在java.util.concurrent包中咱們能找到線程池的定義,其中ThreadPoolExecutor是咱們線程池核心類,首先看看線程池類的主要參數有哪些。後端

  • corePoolSize:線程池的核心大小,也能夠理解爲最小的線程池大小。
  • maximumPoolSize:最大線程池大小。
  • keepAliveTime:空餘線程存活時間,指的是超過corePoolSize的空餘線程達到多長時間才進行銷燬。
  • unit:銷燬時間單位。
  • workQueue:存儲等待執行線程的工做隊列。
  • threadFactory:建立線程的工廠,通常用默認便可。
  • handler:拒絕策略,當工做隊列、線程池全已滿時如何拒絕新任務,默認拋出異常。
線程池工做流程

一、若是線程池中的線程小於corePoolSize時就會建立新線程直接執行任務。多線程

二、若是線程池中的線程大於corePoolSize時就會暫時把任務存儲到工做隊列workQueue中等待執行。架構

三、若是工做隊列workQueue也滿時:當線程數小於最大線程池數maximumPoolSize時就會建立新線程來處理,而線程數大於等於最大線程池數maximumPoolSize時就會執行拒絕策略。工具

線程池分類

Executors是jdk裏面提供的建立線程池的工廠類,它默認提供了4種經常使用的線程池應用,而沒必要咱們去重複構造。性能

  • newFixedThreadPool

    固定線程池,核心線程數和最大線程數固定相等,而空閒存活時間爲0毫秒,說明此參數也無心義,工做隊列爲最大爲Integer.MAX_VALUE大小的阻塞隊列。當執行任務時,若是線程都很忙,就會丟到工做隊列等有空閒線程時再執行,隊列滿就執行默認的拒絕策略。spa

  • newCachedThreadPool

       帶緩衝線程池,從構造看核心線程數爲0,最大線程數爲Integer最大值大小,超過0個的空閒線程在60秒後銷燬,SynchronousQueue這是一個直接提交的隊列,意味着每一個新任務都會有線程來執行,若是線程池有可用線程則執行任務,沒有的話就建立一個來執行,線程池中的線程數不肯定,通常建議執行速度較快較小的線程,否則這個最大線程池邊界過大容易形成內存溢出。線程

  • newSingleThreadExecutor

       單線程線程池,核心線程數和最大線程數均爲1,空閒線程存活0毫秒一樣無心思,意味着每次只執行一個線程,多餘的先存儲到工做隊列,一個一個執行,保證了線程的順序執行。對象

  • newScheduledThreadPool

    調度線程池,即按必定的週期執行任務,即定時任務,對ThreadPoolExecutor進行了包裝而已。

拒絕策略
  • AbortPolicy

      簡單粗暴,直接拋出拒絕異常,這也是默認的拒絕策略。

  • CallerRunsPolicy

       若是線程池未關閉,則會在調用者線程中直接執行新任務,這會致使主線程提交線程性能變慢。

  • DiscardPolicy

       從方法看沒作任務操做,即表示不處理新任務,即丟棄。

  • DiscardOldestPolicy

       拋棄最老的任務,就是從隊列取出最老的任務而後放入新的任務進行執行。

如何提交線程

如能夠先隨便定義一個固定大小的線程池

ExecutorService es = Executors.newFixedThreadPool(3);

提交一個線程

es.submit(xxRunnble);

es.execute(xxRunnble);

submit和execute分別有什麼區別呢?

execute沒有返回值,若是不須要知道線程的結果就使用execute方法,性能會好不少。

submit返回一個Future對象,若是想知道線程結果就使用submit提交,並且它能在主線程中經過Future的get方法捕獲線程中的異常。

如何關閉線程池

es.shutdown();

再也不接受新的任務,以前提交的任務等執行結束再關閉線程池。

es.shutdownNow();

再也不接受新的任務,試圖中止池中的任務再關閉線程池,返回全部未處理的線程list列表。

推薦去個人博客閱讀更多:

1.Java JVM、集合、多線程、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、後端、架構、阿里巴巴等大廠最新面試題

以爲不錯,別忘了點贊+轉發哦!

相關文章
相關標籤/搜索