线程池核心概述
線程池核心概述
- Executors工廠類(lèi)使用?? ??? ??? ??? ??? ??? ?
- Executors工廠類(lèi)底層源碼分析詳解?? ??? ??? ??? ?
- ThreadPoolExecutor自定義線程池?? ??? ??? ??? ?
- ThreadPoolExecutor拒絕策略詳解?? ??? ??? ??? ?
- 計(jì)算機(jī)密集型與IO密集型詳解?? ??? ??? ?
- 如何正確的使用線程池
線程池初步
- 線程池,一般高并發(fā)其實(shí)是一個(gè)非常抽象的概念,要實(shí)現(xiàn)高并發(fā)其實(shí)不僅僅是一個(gè)JAVA 線程集合類(lèi)、或者JAVA基礎(chǔ)層面就能搞定的事情,在互聯(lián)網(wǎng)大廠中,高并發(fā)其實(shí)涉及方方面面,從前端到后端,到支持高并發(fā)的中間組件(redis、zookeper等),最后到數(shù)據(jù)存儲(chǔ),持久化層面等等,都需要對(duì)高并發(fā)做一些考量和設(shè)計(jì)
- 管理控制:首先,從管理角度就是為了更好的控制線程,使用線程池來(lái)幫助我們?nèi)ス芾砭€程,使得我們對(duì)線程的生命周期、初始化、運(yùn)行狀態(tài)、銷(xiāo)毀等各個(gè)環(huán)節(jié)有一個(gè)把控
- 系統(tǒng)資源:另外一點(diǎn),從系統(tǒng)資源的角度考慮,線程池可以控制線程的數(shù)量,根據(jù)任務(wù)的多少去對(duì)線程池中的線程個(gè)數(shù)進(jìn)行添加或者減少,可以回收空閑狀態(tài)的線程,減少線程的頻繁初始化和銷(xiāo)毀,避免不必要的系統(tǒng)開(kāi)銷(xiāo),節(jié)省系統(tǒng)資源,保障穩(wěn)定性
- 應(yīng)用性能:從性能的角度去考慮,線程池可以配合高并發(fā)容器的設(shè)置,對(duì)任務(wù)和工作項(xiàng)進(jìn)行緩存,異步的多線程的去處理任務(wù),從而提高應(yīng)用服務(wù)的吞吐率、消費(fèi)性能,也從而提高單個(gè)線程的利用率
- 兜底策略:從健壯性的角度去分析,線程池提供了很多拒絕策略,我們?cè)谌蝿?wù)過(guò)多或者處理不過(guò)來(lái)的時(shí)候,可以進(jìn)行有效的拒絕策略、降級(jí)方案,以補(bǔ)償?shù)男问竭M(jìn)行處理任務(wù),避免因?yàn)榫€程池的問(wèn)題對(duì)系統(tǒng)產(chǎn)生較為嚴(yán)重的影響
Executors
- JDK提供了一套線程框架Executors,存儲(chǔ)在java.util.concurrent包中,是JDK并發(fā)包的核心
- Executors:線程工廠的角色,通過(guò)Executors可以創(chuàng)建特定功能的線程池
Executors創(chuàng)建線程池的方法
- newFixedThreadPool()方法:該方法返回一個(gè)固定數(shù)量的線程池,該方法的線程數(shù)始終不變,當(dāng)有一個(gè)任務(wù)提交時(shí),若線程池中空閑,則立即執(zhí)行,若沒(méi)有,則會(huì)被暫緩在一個(gè)任務(wù)隊(duì)列中等待有空閑的線程去執(zhí)行
- newSingleThreadPool ()方法:創(chuàng)建一個(gè)線程的線程池,若空閑則執(zhí)行,若沒(méi)有空閑線程則暫緩在任務(wù)列隊(duì)中
- newCachedThreadPool()方法:返回一個(gè)可根據(jù)實(shí)際情況調(diào)整線程個(gè)數(shù)的線程池,不限制最大線程數(shù)量,若有任務(wù),則創(chuàng)建線程,若無(wú)任務(wù)則不創(chuàng)建線程。如果沒(méi)有任務(wù)則線程在60s后自動(dòng)回收(空閑時(shí)間60s)
- newScheduledThreadPool()方法:該方法返回一個(gè)SchededExecutorService對(duì)象,但該線程池可以指定線程的數(shù)量
自定義線程池ThreadPoolExecutor
- 自定義線程池:若Executors工廠無(wú)法滿(mǎn)足我們的需求,可以自己創(chuàng)建自定義線程池,其實(shí)Executors工廠類(lèi)里面的創(chuàng)建線程方法其內(nèi)部實(shí)現(xiàn)均是用了ThreadPoolExecutor這個(gè)類(lèi),這個(gè)類(lèi)可以自定義線程。構(gòu)造方法如下:
- 使用有界隊(duì)列:在使用有界隊(duì)列時(shí),若有新的任務(wù)需要執(zhí)行,如果線程池實(shí)際線程數(shù)小于corePoolSize,則優(yōu)先創(chuàng)建線程,若大于corePoolSize,則會(huì)將任務(wù)加入隊(duì)列,若隊(duì)列已滿(mǎn),則在總線程數(shù)不大于maximumPoolSize的前提下,創(chuàng)建新的線程,若線程數(shù)大于maximumPoolSize,則執(zhí)行拒絕策略。或其他自定義方式
- 使用無(wú)界隊(duì)列:在使用無(wú)界隊(duì)列時(shí):LinkedBlockingQueue。與有界隊(duì)列相比,除非系統(tǒng)資源耗盡,否則無(wú)界的任務(wù)隊(duì)列不存在任務(wù)入隊(duì)失敗的情況。當(dāng)有新任務(wù)到來(lái),系統(tǒng)的線程數(shù)小于corePoolSize時(shí),則新建線程執(zhí)行任務(wù)。當(dāng)達(dá)到corePoolSize后,就不會(huì)繼續(xù)增加。若后續(xù)仍有新的任務(wù)加入,而有沒(méi)有空閑的線程資源,則任務(wù)直接進(jìn)入隊(duì)列等待。若任務(wù)創(chuàng)建和處理的速度差異很大,無(wú)界隊(duì)列會(huì)保持快速增長(zhǎng),直到耗盡系統(tǒng)內(nèi)存
線程池的拒絕策略
- AbortPolicy:直接拋出異常阻止系統(tǒng)正常工作
- CallerRunsPolicy:只要線程池未關(guān)閉,該策略直接在調(diào)用者線程中,運(yùn)行當(dāng)前被丟棄的任務(wù)
- DiscardOldestPolicy:丟棄最老的一個(gè)請(qǐng)求,嘗試再次提交當(dāng)前任務(wù)
- DiscardPolicy:丟棄無(wú)法處理的任務(wù),不給予任何處理
- 如果需要自定義拒絕策略可以實(shí)現(xiàn)RejectedExecutionHandler接口 //RejectedExecutionHandler接口 public class MyRejected implements RejectedExecutionHandler{public MyRejected(){}@Overridepublic void rejectExecution(Runnable r,ThreadPoolExecutor executor){} }
如何使用好線程池
- 線程個(gè)數(shù)大小的設(shè)置
- 線程池相關(guān)參數(shù)配置
- 利用Hook嵌入你的行為
- 線程池的關(guān)閉
線程池大小設(shè)置(計(jì)算密集型/IO密集型)
線程池相關(guān)參數(shù)配置注意事項(xiàng)
利用Hook嵌入你的行為
???????關(guān)閉線程池
相關(guān)代碼
package com.bfxy.thread.core.pool;import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit;public class UseThreadPoolExecutor {public static void main(String[] args) {ThreadPoolExecutor pool = new ThreadPoolExecutor(1, // corePoolSize: 核心線程數(shù),線程池初始化的時(shí)候就會(huì)被創(chuàng)建3, // maximumPoolSize: 線程池的最大上限 //在使用無(wú)界隊(duì)列的時(shí)候, 此參數(shù) 不起作用60, //線程的存活時(shí)間TimeUnit.SECONDS,//workQueue:BlockingQueue接口下面的實(shí)現(xiàn)類(lèi)//new ArrayBlockingQueue<>(2), //使用有界隊(duì)列: ArrayBlockingQueuenew LinkedBlockingQueue<>(), //使用無(wú)界隊(duì)列: LinkedBlockingQueuenew ThreadFactory() { //threadFactory 線程工廠, 用于獲取一個(gè)新的線程, 然后把該線程 投遞到我們的線程池中去@Overridepublic Thread newThread(Runnable r) {Thread th = new Thread(r, "order-thread");if(th.getPriority() != Thread.NORM_PRIORITY) {th.setPriority(Thread.NORM_PRIORITY);}if(th.isDaemon()) {th.setDaemon(false);}return th;}}, //使用無(wú)界隊(duì)列時(shí), 拒絕策略不起到作用new RejectedExecutionHandler() {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {System.err.println("當(dāng)前的任務(wù)已經(jīng)被拒絕: " + r.toString());}});Task t1 = new Task(1);Task t2 = new Task(2);Task t3 = new Task(3);Task t4 = new Task(4);Task t5 = new Task(5);Task t6 = new Task(6);/**//線程池提交任務(wù)的方法:pool.execute(t1); //execute: 如果你的任務(wù)沒(méi)有返回值, 則使用該方法提交任務(wù)pool.submit(t1); //submit: 如果你的任務(wù)有返回值, 則使用該方法提交任務(wù), 返回一個(gè)Future對(duì)象(Future模式)*//*** * 在使用有界隊(duì)列時(shí):* 1 若有新的任務(wù)需要執(zhí)行,如果線程池實(shí)際線程數(shù)小于corePoolSize,則優(yōu)先創(chuàng)建線程* 2 若大于corePoolSize,則會(huì)將任務(wù)加入隊(duì)列* 3 若隊(duì)列已滿(mǎn),則在總線程數(shù)不大于maximumPoolSize的前提下,創(chuàng)建新的線程* 4 若線程數(shù)大于maximumPoolSize,則執(zhí)行拒絕策略。*/// 1 若有新的任務(wù)需要執(zhí)行,如果線程池實(shí)際線程數(shù)小于corePoolSize,則優(yōu)先創(chuàng)建線程pool.execute(t1); //core size = 1 t1任務(wù)會(huì)被核心線程執(zhí)行// 2 若大于corePoolSize,則會(huì)將任務(wù)加入隊(duì)列pool.execute(t2); // 有界隊(duì)列容量為: 2pool.execute(t3);// 3 若隊(duì)列已滿(mǎn),則在總線程數(shù)不大于maximumPoolSize的前提下,創(chuàng)建新的線程, 并執(zhí)行該任務(wù)pool.execute(t4); // 線程池中的總線程數(shù) 2 , maximumPoolSize = 3 pool.execute(t5); // 線程池中的總線程數(shù) 3 , maximumPoolSize = 3 // 4 若線程數(shù)大于maximumPoolSize,則執(zhí)行拒絕策略。pool.execute(t6);pool.shutdown();} }?
總結(jié)
- 上一篇: 信用卡溢缴款可以用于快捷支付吗?做好这点
- 下一篇: TDengine安装教程