既然Java中支持以多線程的方式來執行相應的任務,但爲何在JDK1.5中又提供了線程池技術呢?這個問題你們自行腦補,多動腦,確定沒壞處,哈哈哈。。。segmentfault
提及Java中的線程池技術,在不少框架和異步處理中間件中都有涉及,並且性能經受起了長久的考驗。能夠這樣說,Java的線程池技術是Java最核心的技術之一,在Java的高併發領域中,Java的線程池技術是一個永遠繞不開的話題。既然Java的線程池技術這麼重要(怎麼能說是這麼重要呢?那是至關的重要,那傢伙老重要了,哈哈哈),那麼,本文咱們就來簡單的說下線程池與ThreadPoolExecutor類。至於線程池中的各個技術細節和ThreadPoolExecutor的底層原理和源碼解析,咱們會在【高併發專題】專欄中進行深度解析。緩存
引言:本文是高併發中線程池的開篇之做,就暫時先不深刻講解,只是讓你們從總體上認識下線程池中最核心的類之一——ThreadPoolExecutor,關於ThreadPoolExecutor的底層原理和源碼實現,以及線程池中的其餘技術細節的底層原理和源碼實現,咱們會在【高併發專題】接下來的文章中,進行死磕。微信
(1)每次new Thread新建對象,性能差。
(2)線程缺少統一管理,可能無限制的新建線程,相互競爭,有可能佔用過多系統資源致使死機或OOM。
(3)缺乏更多的功能,如更多執行、按期執行、線程中斷。
(4)其餘弊端,你們自行腦補,多動腦,沒壞處,哈哈。多線程
(1)重用存在的線程,減小對象建立、消亡的開銷,性能佳。
(2)能夠有效控制最大併發線程數,提升系統資源利用率,同時能夠避免過多資源競爭,避免阻塞。
(3)提供定時執行、按期執行、單線程、併發數控制等功能。
(4)提供支持線程池監控的方法,可對線程池的資源進行實時監控。
(5)其餘好處,你們自行腦補,多動腦,沒壞處,哈哈。併發
線程池中的一些接口和類的結構關係以下圖所示。框架
後文會死磕這些接口和類的底層原理和源碼。異步
注意:不須要對線程池的狀態作特殊的處理,線程池的狀態是線程池內部根據方法自行定義和處理的。高併發
(1)CPU密集型任務,就須要儘可能壓榨CPU,參考值能夠設置爲NCPU+1(CPU的數量加1)。
(2)IO密集型任務,參考值能夠設置爲2*NCPU(CPU數量乘以2)性能
ThreadPoolExecutor參數最多的構造方法以下:spa
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler rejectHandler)
其餘的構造方法都是調用的這個構造方法來實例化對象,能夠說,咱們直接分析這個方法以後,其餘的構造方法咱們也明白是怎麼回事了!接下來,就對此構造方法進行詳細的分析。
注意:爲了更加深刻的分析ThreadPoolExecutor類的構造方法,會適當調整參數的順序進行解析,以便於你們更能深刻的理解ThreadPoolExecutor構造方法中每一個參數的做用。
上述構造方法接收以下參數進行初始化:
(1)corePoolSize:核心線程數量。
(2)maximumPoolSize:最大線程數。
(3)workQueue:阻塞隊列,存儲等待執行的任務,很重要,會對線程池運行過程產生重大影響。
其中,上述三個參數的關係以下所示:
根據上述三個參數的配置,線程池會對任務進行以下處理方式:
當提交一個新的任務到線程池時,線程池會根據當前線程池中正在運行的線程數量來決定該任務的處理方式。處理方式總共有三種:直接切換、使用無限隊列、使用有界隊列。
根據上面三個參數,咱們能夠簡單得出如何下降系統資源消耗的一些措施:
接下來,咱們繼續看ThreadPoolExecutor的構造方法的參數。
(4)keepAliveTime:線程沒有任務執行時最多保持多久時間終止
當線程池中的線程數量大於corePoolSize時,若是此時沒有新的任務提交,核心線程外的線程不會當即銷燬,須要等待,直到等待的時間超過了keepAliveTime就會終止。
(5)unit:keepAliveTime的時間單位
(6)threadFactory:線程工廠,用來建立線程
默認會提供一個默認的工廠來建立線程,當使用默認的工廠來建立線程時,會使新建立的線程具備相同的優先級,而且是非守護的線程,同時也設置了線程的名稱
(7)rejectHandler:拒絕處理任務時的策略
若是workQueue阻塞隊列滿了,而且沒有空閒的線程池,此時,繼續提交任務,須要採起一種策略來處理這個任務。
線程池總共提供了四種策略:
(1)execute():提交任務,交給線程池執行
(2)submit():提交任務,可以返回執行結果 execute+Future
(3)shutdown():關閉線程池,等待任務都執行完
(4)shutdownNow():當即關閉線程池,不等待任務執行完
(1)getTaskCount():線程池已執行和未執行的任務總數
(2)getCompletedTaskCount():已完成的任務數量
(3)getPoolSize():線程池當前的線程數量
(4)getCorePoolSize():線程池核心線程數
(5)getActiveCount():當前線程池中正在執行任務的線程數量
關注【冰河技術】微信公衆號,天天推送深度技術乾貨