1别渔、線程池的三個好處:
- 降低資源消耗√锇停可以重復利用已創(chuàng)建的線程钠糊,降低創(chuàng)建/銷毀線程的開銷
- 提高響應速度。
- 提高線程的可管理性壹哺。統(tǒng)一分配抄伍、調(diào)優(yōu)、監(jiān)控管宵。
2截珍、線程池的處理流程
新任務提交至線程池后的處理流程:
- 1.核心線程池是否已滿,如果沒滿箩朴,則創(chuàng)建一個線程執(zhí)行任務岗喉,如果滿了,則進入下一個流程
- 2.判斷隊列是否已經(jīng)滿了炸庞,如果沒滿钱床,則將任務存儲在隊列中,如果滿了埠居,則進入下一個流程
- 3.判斷線程池是否已經(jīng)滿了查牌,如果沒滿,則創(chuàng)建線程執(zhí)行任務滥壕,如果滿了纸颜,則按照策略處理無法執(zhí)行的任務。
3绎橘、線程池的使用
3.1胁孙、線程池的創(chuàng)建
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize:線程池的基本大小
- maximumPoolSize:線程池的最大線程數(shù)
- keepAliveTime:線程的活動的保持時間。當線程空閑之后称鳞,保持存活的時間涮较,如果任務量大,而任務的執(zhí)行時間又短的話胡岔,可以增大線程池的存活時間法希,提高線程的利用率
- TimeUnit:線程活動保持時間的單位
- BlockingQueue:用于存放任務的阻塞隊列,隊列的選擇可以參考java中的阻塞隊列
- ThreadFactory:用于設置創(chuàng)建線程的工廠靶瘸。
- RejectedExecutionHandler:飽和策略苫亦。即當線程和隊列都已經(jīng)滿了的時候,應該采取什么樣的策略來處理新提交的任務怨咪,默認策略是AbortPolicy(拋出異常)屋剑,其他的策略還有:CallerRunsPolicy(只用調(diào)用者所在線程來運行任務),DiscardOldestPolicy(丟棄隊列里最近的一個任務诗眨,并執(zhí)行當前任務)唉匾,DiscardPolicy(不處理,丟棄掉)
3.2匠楚、向線程池提交任務
提交任務有兩種方法巍膘,分別是execute()和submit()。
execute()方法適用于任務提交之后沒有返回值的這種情況芋簿,因為沒有返回值峡懈,所以提交任務之后我們也無法判斷任務是否執(zhí)行成功。
submit方法適用于提交任務之后有返回值的情況与斤,它會返回一個Future類型的對象肪康,可以通過future.get()方法來獲取返回值,get()會阻塞線程直到任務完成撩穿。
3.3磷支、關閉線程池
關閉線程池有兩種方法,分別是shutdown()和shutdownNow()食寡,它們的原理都是遍歷線程池中所有的線程雾狈,分別調(diào)用每個線程池的interrupt()方法來中斷線程。但是它們存在一定的區(qū)別抵皱,shutdownNow首先將線程池的狀態(tài)設置成STOP善榛,然后嘗試停止所有的正在執(zhí)行或暫停任務的線程,并返回等待執(zhí)行任務的列表叨叙,而shutdown只是將線程池的狀態(tài)設置成SHUTDOWN狀態(tài)锭弊,然后中斷所有沒有正在執(zhí)行任務的線程。
3.4擂错、合理的配置線程池
線程池配置的分析角度
- 任務的性質:IO密集型還是CPU密集型味滞,cup密集型可以配置小一點的線程數(shù),io密集型可以配置多的線程數(shù)
- 任務的優(yōu)先級:可以用PriorityBlockingQueue隊列來處理
- 任務處理時間的長短
- 任務的依賴性:比如說是否依賴數(shù)據(jù)庫連接
線程池的任務隊列的選擇建議使用有界隊列钮呀,因為如果任務太多剑鞍,有界隊列可以拋出異常便于我們排查,而無界隊列會使隊列中的任務越來越多爽醋,可能導致?lián)螡M內(nèi)存蚁署,導致整個系統(tǒng)的不可用。