新鄉(xiāng)營銷型網(wǎng)站建設(shè)產(chǎn)品營銷推廣策略
目錄
一.什么是線程池
二.線程池的實現(xiàn)原理
🎈為什么要有工廠模式?
三.線程池的構(gòu)造方法解讀
🎈線程池的拒絕策略
四.自己實現(xiàn)一個線程池
一.什么是線程池
簡單來說,線程池就好比一塊魚塘,魚塘中的每條魚就是一個線程。那么為什么要有這個線程池呢?就好比 一個“渣女\渣男”,當他和A在一起的時候,如果想和B在一起,那么就需要先想辦法和A分手,再和B搞好關(guān)系,最終和B在一起。如果她和A談的時候,已經(jīng)找好了B C D,此時就可以直接拿來無縫銜接~~
其實線程池也就大概這個作用,里面存放一些線程,需要用的時候直接拿來使用。
二.線程池的實現(xiàn)原理
我們先來看線程池是如何創(chuàng)建的:
package Pool;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class threadPoolDemo {public static void main(String[] args) {ExecutorService executor = Executors.newSingleThreadExecutor();}
}
很明顯,此處的線程池竟然不是 new 出來的,那么它是如何被實例化的呢?其實這里就使用了一種設(shè)計模式:工廠模式。
🎈為什么要有工廠模式?
其實工廠模式就時給Java中的構(gòu)造方法填坑的,我們的構(gòu)造方法其實時有很大缺陷的,我們來看以下例子。
我們期望這個Point類,初始化的時候能夠傳入 double x,double y,用來構(gòu)造笛卡爾坐標系
我們又希望在不創(chuàng)建其他類的情況下,這個Point類,?初始化的時候能夠傳入 double r,double a,用來構(gòu)造極坐標系。
但是構(gòu)造方法也是方法,此時的方法由于參數(shù)個數(shù)和參數(shù)的類型都相同,就會編譯失敗,那么就沒辦法滿足期望!
此時我們可以再寫一個類:
此時這個類中又兩個靜態(tài)方法,一個是構(gòu)造笛卡爾坐標系,并且返回。一個是構(gòu)造及坐標系,并且返回對象。
那么我們就可以使用以下語句來分別調(diào)用:
Point p1 = PointFactory.makePintByXY(10,20)?
Point p2?= PointFactory.makePintByRA(12,63)?
此時通過PointFactory類,來給Point類傳入需要的值就可以了。
那么線程池也是通過這樣的方式來進行創(chuàng)建的:
三.線程池的構(gòu)造方法解讀
從Excutor這個工廠類的源碼中可以得到以下:
其實線程的創(chuàng)建又被封裝到了一個叫做ThreadPoolExecutor的類中
點開ThreadPoolExecutor,可以得到如下圖片:
其中的每個參數(shù)的意思是這樣的:
第一個是核心線程數(shù), 第二個是最大線程數(shù)
線程池中的線程數(shù)目是可以動態(tài)變化的
范圍就是【int corPoolSize. ~ int maxmumPoolSize】
什么是核心線程:
就好比一個公司中有正式員工(核心線程)和實習生,總的員工數(shù)目不能超過一定的值。當人手不夠用就招實習生,這樣既可以滿足效率的需求,又可以避免過多的開銷。
第三個是線程的可存活時間
第四個TimeUnit unit是用來設(shè)置非核心線程閑置超時時長(keepAliveTime)的單位。當一個非核心線程的閑置時間超過這個參數(shù)所設(shè)定的時長時,該線程就會被銷毀掉。
第五個比較重要
第六個是線程池的拒絕策略,也就是當所有線程都處于忙碌狀態(tài),如果還往線程池中添加元素,線程池所做的操作。
這些構(gòu)造方法,第一個和第五個以及第六個是需要重點掌握的。?
下面來單獨講講第六個參數(shù):拒絕策略
🎈線程池的拒絕策略
所謂的拒絕策略,其實就是如果線程池中每個線程都是處于忙碌的狀態(tài),如何應(yīng)對新來的線程任務(wù)。
舉個例子:如果我周一到周五都是滿課,此時我一朋友讓我給他去代課,那么此時我如何應(yīng)對?此時就會有相應(yīng)的應(yīng)對策略:
- AbortPolicy(默認策略):這是默認的拒絕策略,它會拋出一個未檢查的RejectedExecutionException,以指示任務(wù)被拒絕。也就是我本來都滿課了,朋友還讓我去代課,此時我就直接崩潰,代課和我自己的課我都不去上了,直接崩潰!
- CallerRunsPolicy:這個策略不會拋出異常。相反,它會將任務(wù)退回給調(diào)用線程,讓它自己運行這個任務(wù)。 也就是讓我朋友自己去上課。
- DiscardOldestPolicy:此策略會丟棄隊列中等待最久的任務(wù),并立即返回給調(diào)用者。也就是我丟棄我課程中一節(jié)課,去給他代課。
- DiscardPolicy:這個策略會靜默地丟棄被拒絕的任務(wù)。也就是說,它不會拋出任何異常,也不會通知任務(wù)被拒絕。 也就是我拒絕去給他代課,我自己上自己的課。然后我朋友也不去上課了,那么這個課(任務(wù)) 也就黃了。
四.自己實現(xiàn)一個線程池
? 實現(xiàn)線程池一個最關(guān)鍵的步驟就是拒絕策略,那么說明拒絕策略呢?
由于之前學過阻塞隊列的知識,這里就先用阻塞隊列來實現(xiàn)以下。
那么這個就是一種自己定義的新的拒絕策略,那就是一直等待~
package Pool;import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue;class MyPoolDemo {//一個隊列BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);//通過這個方法,把任務(wù)添加到隊列當中public void submit(Runnable task) throws InterruptedException {queue.put(task); //往阻塞隊列中放入元素}public MyPoolDemo(int n) throws InterruptedException {//構(gòu)造方法for (int i = 0; i < n; i++) {Thread t = new Thread(() -> {//讓這個線程從隊列中消費任務(wù)并且進行執(zhí)行try {//如果隊列中沒有元素,那就阻塞等待//一旦隊列中有了任務(wù),那么就立即執(zhí)行take方法獲取到任務(wù)并且開始執(zhí)行Runnable task = task = queue.take();task.run();} catch (InterruptedException e) {throw new RuntimeException(e);}});t.start();}}} public class RunDemo {public static void main(String[] args) throws InterruptedException {/*** 步驟理解:* 1.創(chuàng)建線程池并且指定線程數(shù)目是 20 ,在實例化線程池的時候已經(jīng)創(chuàng)建好了20個線程* 2.這20個線程都在等待 take 獲取到任務(wù)隊列中的任務(wù)* 3.for 語句 循環(huán) 1000次,每次循環(huán)都會提交任務(wù)到任務(wù)隊列* 4.一但任務(wù)隊列里面有元素,這20個線程就會立馬獲取到,并且執(zhí)行*/MyPoolDemo myPoolDemo = new MyPoolDemo(20);int taskCount = 1000;while (true) {for (int i = 0; i < taskCount; i++) {int id = i;myPoolDemo.submit(new Runnable() {@Overridepublic void run() {System.out.println("執(zhí)行任務(wù):" + id);}});}}}}
運行結(jié)果:
代碼解讀:
1.線程池里的線程是需要執(zhí)行任務(wù)的,這個任務(wù)可以放到? ? BlockingQueue 這個阻塞隊列中。為什么要使用阻塞隊列呢?當線程池中的線程都在工作,此時就直接等待阻塞。
2.submit 方法接受一個實例化好的Runnable類型的任務(wù),負責往隊列中添加元素
3.?MyPoolDemo(int n) 是這個類的構(gòu)造放法,當實例化這個類的時候,被指定的 n 就是要創(chuàng)建的線程數(shù)量。
4. 由運行結(jié)果可以得出:當線程數(shù)量為20的時候,可以看到任務(wù)被隨即執(zhí)行完了。
總結(jié):Java線程池是Java并發(fā)編程中一個重要的概念,它用于管理和控制線程的創(chuàng)建、銷毀,以及任務(wù)提交和執(zhí)行。線程池的主要目的是減少創(chuàng)建和銷毀線程的開銷,提高性能。?