java并发之线程池
生活随笔
收集整理的這篇文章主要介紹了
java并发之线程池
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- @[TOC]
- 1:ThreadPoolExcutor
- (1):ThreadPoolExcutor構(gòu)造函數(shù)
- (2):構(gòu)造函數(shù)的參數(shù)
- (3):圖示 核心線程數(shù) 最大線程數(shù) 阻塞隊(duì)列
- (4):一個(gè)任務(wù)在線程池的流程
- 2:固定容量的線程池(newFixedThreadPool)
- (1):構(gòu)造函數(shù)
- (2):特點(diǎn)
- (3):代碼示例
- 3:可緩存的線程池
- (1):構(gòu)造函數(shù)
- (2):特點(diǎn)
- 4:單線程池
- (1):構(gòu)造函數(shù)
- (2):特點(diǎn)
- 5:固定數(shù)量線程池...和ThreadPoolExecutor的區(qū)別聯(lián)系
- (1)如何創(chuàng)建固定數(shù)量的線程池,可緩存的線程池,單線程池
- (2)和ThreadPoolExcutor的聯(lián)系
- 5:自定義線程池
- (1):自定義線程池的規(guī)則
- (2):關(guān)于線程池的 Executor工具類的execute()方法
- (3):代碼示例
- (4):關(guān)于拒絕策略
- 6:關(guān)閉線程池
- @[TOC]
- 1:ThreadPoolExcutor
- (1):ThreadPoolExcutor構(gòu)造函數(shù)
- (2):構(gòu)造函數(shù)的參數(shù)
- (3):圖示 核心線程數(shù) 最大線程數(shù) 阻塞隊(duì)列
- (4):一個(gè)任務(wù)在線程池的流程
- 2:固定容量的線程池(newFixedThreadPool)
- (1):構(gòu)造函數(shù)
- (2):特點(diǎn)
- (3):代碼示例
- 3:可緩存的線程池
- (1):構(gòu)造函數(shù)
- (2):特點(diǎn)
- 4:單線程池
- (1):構(gòu)造函數(shù)
- (2):特點(diǎn)
- 5:固定數(shù)量線程池...和ThreadPoolExecutor的區(qū)別聯(lián)系
- (1)如何創(chuàng)建固定數(shù)量的線程池,可緩存的線程池,單線程池
- (2)和ThreadPoolExcutor的聯(lián)系
- 5:自定義線程池
- (1):自定義線程池的規(guī)則
- (2):關(guān)于線程池的 Executor工具類的execute()方法
- (3):代碼示例
- (4):關(guān)于拒絕策略
- 6:關(guān)閉線程池
1:ThreadPoolExcutor
(1):ThreadPoolExcutor構(gòu)造函數(shù)
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler);}(2):構(gòu)造函數(shù)的參數(shù)
- corePoolSize核心線程數(shù)目(最多保留的線程數(shù))
- maximumPoolSize最大線程數(shù)目
- keepAliveTime生存時(shí)間-針對(duì)救急線程
- unit時(shí)間單位-針對(duì)救急線程
- workQueue阻塞隊(duì)列
- threadFactory線程工廠-可以為線程創(chuàng)建時(shí)起個(gè)好名字
- handler拒絕策略
(3):圖示 核心線程數(shù) 最大線程數(shù) 阻塞隊(duì)列
- 核心線程數(shù)就是我們銀行一直正常開的窗口
- 阻塞隊(duì)列就是銀行常用窗口人數(shù)滿了,然后就在后候客區(qū)等待的顧客
- 救急線程就是阻塞隊(duì)列滿了 不得不再開幾個(gè)營(yíng)業(yè)窗口
- 最大線程數(shù)目 = 救急線程數(shù)目 + 核心線程數(shù)目
(4):一個(gè)任務(wù)在線程池的流程
- 線程池中剛開始沒有線程,當(dāng)一個(gè)任務(wù)提交給線程池后,線程池會(huì)創(chuàng)建一個(gè)新線程來執(zhí)行任務(wù)。
- 當(dāng)線程數(shù)達(dá)到corePoolSize并沒有線程空閑,這時(shí)再加入任務(wù),新加的任務(wù)會(huì)被加入workQueue隊(duì)列排
隊(duì),直到有空閑的線程。 - 如果隊(duì)列選擇了有界隊(duì)列,那么任務(wù)超過了隊(duì)列大小時(shí),會(huì)創(chuàng)建maximumPoolSize-corePoolSize數(shù)目的
線程來救急。 - 如果線程到達(dá)maximumPoolSize仍然有新任務(wù)這時(shí)會(huì)執(zhí)行拒絕策略。拒絕策略jd提供了4種實(shí)現(xiàn),其它
著名框架也提供了實(shí)現(xiàn)- AbortPolicy讓調(diào)用者拋出RejectedExecutionException異常,這是默認(rèn)策略
- CallerRunsPolicy讓調(diào)用者運(yùn)行任務(wù)
- DiscardPolicy放棄本次任務(wù)
- DiscardOldestPolicy放棄隊(duì)列中最早的任務(wù),本任務(wù)取而代之
- Dubbo的實(shí)現(xiàn),在拋出RejectedExecutionException異常之前會(huì)記錄日志,并dump線程棧信息,方便定
位問題 - Netty的實(shí)現(xiàn),是創(chuàng)建一個(gè)新線程來執(zhí)行任務(wù)
- ActiveMQ的實(shí)現(xiàn),帶超時(shí)等待(60s)嘗試放入隊(duì)列,類似我們之前自定義的拒絕策略
- PinPoint的實(shí)現(xiàn),它使用了一個(gè)拒絕策略鏈,會(huì)逐一嘗試策略鏈中每種拒絕策略
- 當(dāng)高峰過去后,超過corePoolSize的救急線程如果一段時(shí)間沒有任務(wù)做,需要結(jié)束節(jié)省資源,這個(gè)時(shí)間由
- keepAliveTime和unit來控制。
2:固定容量的線程池(newFixedThreadPool)
(1):構(gòu)造函數(shù)
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}(2):特點(diǎn)
- 核心線程數(shù)==最大線程數(shù)
(沒有救急線程被創(chuàng)建),因此也無(wú)需超時(shí)時(shí)間 - 阻塞隊(duì)列是無(wú)界的,可以放任意數(shù)量的任務(wù)
- 評(píng)價(jià)
適用于任務(wù)量已知,相對(duì)耗時(shí)的任務(wù)
(3):代碼示例
public class text02 {public static void main(String[] args) {ExecutorService executorService1 = Executors.newFixedThreadPool(2);//固定線程數(shù) 核心線程數(shù) == 最大線程數(shù) 無(wú)救急線程 并且線程不會(huì)關(guān)閉//線程池里開啟一個(gè)線程 并執(zhí)行一個(gè)任務(wù)executorService1.execute(() -> {System.out.println(Thread.currentThread().getName() + "->1");});//線程池再開啟一個(gè)線程 并執(zhí)行一個(gè)任務(wù)executorService1.execute(() -> {System.out.println(Thread.currentThread().getName() + "->2");});//此時(shí)又來了一個(gè)任務(wù),因?yàn)榍懊娴娜蝿?wù)執(zhí)行時(shí)間比較短,所以再來任務(wù)的話,不會(huì)進(jìn)入阻塞隊(duì)列//而是會(huì)用前面已經(jīng)開啟的線程繼續(xù)執(zhí)行任務(wù)executorService1.execute(()-> {System.out.println(Thread.currentThread().getName()+"->3");});} }3:可緩存的線程池
(1):構(gòu)造函數(shù)
public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());(2):特點(diǎn)
- 核心線程數(shù)為0,最大線程數(shù)為Interger.MAX_VALUE,救急線程的空閑存活時(shí)間是60s
- 沒有核心線程 全部都是救急線程
- 救急線程可以無(wú)線創(chuàng)建
- 隊(duì)列采用了SynchronousQueue實(shí)現(xiàn)特點(diǎn)是,它沒有容量,沒有線程來取是放不進(jìn)去的(一手交錢、一手
交貨) - 評(píng)價(jià)
整個(gè)線程池表現(xiàn)為線程數(shù)會(huì)根據(jù)任務(wù)量不斷增長(zhǎng),沒有上限,當(dāng)任務(wù)執(zhí)行完畢,空閑1分鐘后釋放線
程。==適合任務(wù)數(shù)處比較密集,但每個(gè)任務(wù)執(zhí)行時(shí)間較短的情況 ==(如果任務(wù)時(shí)間比較長(zhǎng),那么就會(huì)不斷創(chuàng)建線程,消耗系統(tǒng)性能)
4:單線程池
(1):構(gòu)造函數(shù)
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}(2):特點(diǎn)
- 核心線程數(shù)為1,最大線程數(shù)也為1,這個(gè)線程一直存活,不會(huì)釋放
- 隊(duì)列是無(wú)界隊(duì)列,當(dāng)任務(wù)數(shù)目大于1的時(shí)候,任務(wù)會(huì)被放入無(wú)界隊(duì)列
- 和普通單線程的區(qū)別
自己創(chuàng)建一個(gè)單線程串行執(zhí)行任務(wù),如果任務(wù)執(zhí)行失敗而終止那么沒有任何補(bǔ)救措施,而線程池還會(huì)新建
一個(gè)線程,保證池的正常工作 - 和固定容量的線程池只開辟一個(gè)線程的區(qū)別
Executors…newSingleThreadExecutor()線程個(gè)數(shù)始終為1,不能修改
FinalizableDelegatedExecutorService應(yīng)用的是裝飾器模式,只對(duì)外暴露了ExecutorService接口,因此不
能調(diào)用ThreadPoolExecutor中特有的方法
Executors.newFixedThreadPool(1)初始時(shí)為l,以后還可以修改
對(duì)外暴露的是ThreadPoolExecutor對(duì)象,可以強(qiáng)轉(zhuǎn)后調(diào)用setCorePoolSize等方法進(jìn)行修改
5:固定數(shù)量線程池…和ThreadPoolExecutor的區(qū)別聯(lián)系
(1)如何創(chuàng)建固定數(shù)量的線程池,可緩存的線程池,單線程池
ExecutorService executorService1 = Executors.newFixedThreadPool(5);ExecutorService executorService2 = Executors.newSingleThreadExecutor();ExecutorService executorService3 = Executors.newCachedThreadPool();(2)和ThreadPoolExcutor的聯(lián)系
我們將對(duì)應(yīng)的線程池點(diǎn)進(jìn)去,發(fā)現(xiàn)其實(shí)底層還是靠ThreadPoolExcutors來實(shí)現(xiàn)
5:自定義線程池
(1):自定義線程池的規(guī)則
我們采用 ThreadPoolExcutors來創(chuàng)建,這使阿里爸爸開發(fā)手冊(cè)中明文推薦的,主要是其他線程池實(shí)現(xiàn)類都有OOM(內(nèi)存用完了)的風(fēng)險(xiǎn)
(2):關(guān)于線程池的 Executor工具類的execute()方法
- 當(dāng)有新的任務(wù)要處理時(shí),先看線程池中的線程數(shù)量是否大于corePoolSize,再看緩沖隊(duì)列workQueue是否滿,最后看線程池 中的線程數(shù)量是否大于maximumPoolSize
另外,當(dāng)線程池中的線程數(shù)量大于corePoolSize時(shí),如果里面有線程的空閑時(shí)間超過了keepAliveTime,就將其移除線程池 - 也就是excutor()方法中會(huì)創(chuàng)建線程執(zhí)行任務(wù),但是這個(gè)線程的數(shù)量是有限的,雖然數(shù)量有限,但是核心線程可以重復(fù)執(zhí)行任務(wù),救急線程在空閑存活時(shí)間的里也可以執(zhí)行任務(wù)
(3):代碼示例
public class text03 {public static void main(String[] args) {Executors.newCachedThreadPool();ThreadPoolExecutor pool = new ThreadPoolExecutor(2,//核心線程數(shù)5,//最大線程數(shù) = 核心線程數(shù) + 救急線程數(shù)(當(dāng)阻塞隊(duì)列)3,//救濟(jì)線程的空閑存活時(shí)間TimeUnit.MINUTES,//時(shí)間的單位new LinkedBlockingQueue<>(3),//阻塞隊(duì)列默認(rèn)為無(wú)界隊(duì)列但是我將其設(shè)置為3Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()//拒絕策略,一旦超過最大線程數(shù)就拋異常);//我們?cè)谝粋€(gè)for循環(huán)內(nèi)//當(dāng)我們同時(shí)來了9個(gè)任務(wù)的時(shí)候,會(huì)有2個(gè)任務(wù)去核心線程去執(zhí)行,還有3個(gè)任務(wù)進(jìn)入阻塞隊(duì)列,還有3個(gè)任務(wù)會(huì)去救急線程那去執(zhí)行//那么我們的還有一個(gè)線程無(wú)法執(zhí)行,此時(shí)會(huì)采取拒絕策略 ;//我們阻塞隊(duì)列中的任務(wù)是等著 救急線程 或者 核心線程去執(zhí)行完手里的任務(wù)去執(zhí)行的for (int i = 1; i <= 9; i++) {pool.execute(()->{System.out.println(Thread.currentThread().getName()+"--->"+"ok");});}} }(4):關(guān)于拒絕策略
- new ThreadPoolExecutor.AbortPolicy() 這個(gè)是默認(rèn)的拒絕策略 是拋出異常的
- new ThreadPoolExecutor.CallerRunsPolicy() 這個(gè)是讓調(diào)用者去執(zhí)行這個(gè)任務(wù)
- new ThreadPoolExecutor.DiscardPolicy() 這個(gè)是直接丟掉任務(wù) 不拋異常
- new ThreadPoolExecutor.DiscardOldestPolicy() 丟掉最早執(zhí)行的任務(wù) 然后再執(zhí)行本任務(wù)
6:關(guān)閉線程池
總結(jié)
以上是生活随笔為你收集整理的java并发之线程池的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 往国外汇款怎么汇?
- 下一篇: 八大排序算法交换排序算法