線程的創(chuàng)建和效率都需要消耗處理器(cpu)的資源,所以我們?cè)谑褂镁€程時(shí)需要注意,你的每一個(gè)動(dòng)作都是需要為它買(mǎi)單的,也正是因?yàn)榫€程的使用需要謹(jǐn)慎,所以java對(duì)線程的管理也進(jìn)行了封裝,就是今天要說(shuō)的線程池,目前java主要封裝了大概4大種類(lèi)型的線程池,下面簡(jiǎn)單來(lái)介紹一下。
四大類(lèi)型的線程池
* newCachedThreadPool創(chuàng)建一個(gè)可緩存線程池,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程,若無(wú)可回收,則新建線程。
* newFixedThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待。
* newScheduledThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池,支持定時(shí)及周期性任務(wù)執(zhí)行。
* newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO,
LIFO, 優(yōu)先級(jí))執(zhí)行。
線程池里主要的三個(gè)參數(shù)
corePoolSize:
線程池的基本大小,即在沒(méi)有任務(wù)需要執(zhí)行的時(shí)候線程池的大小,并且只有在工作隊(duì)列滿了的情況下才會(huì)創(chuàng)建超出這個(gè)數(shù)量的線程。這里需要注意的是:在剛剛創(chuàng)建ThreadPoolExecutor的時(shí)候,線程并不會(huì)立即啟動(dòng),而是要等到有任務(wù)提交時(shí)才會(huì)啟動(dòng),除非調(diào)用了prestartCoreThread/prestartAllCoreThreads事先啟動(dòng)核心線程。再考慮到keepAliveTime和allowCoreThreadTimeOut超時(shí)參數(shù)的影響,所以沒(méi)有任務(wù)需要執(zhí)行的時(shí)候,線程池的大小不一定是corePoolSize。
maximumPoolSize:
線程池中允許的最大線程數(shù),線程池中的當(dāng)前線程數(shù)目不會(huì)超過(guò)該值。如果隊(duì)列中任務(wù)已滿,并且當(dāng)前線程個(gè)數(shù)小于maximumPoolSize,那么會(huì)創(chuàng)建新的線程來(lái)執(zhí)行任務(wù)。這里值得一提的是largestPoolSize,該變量記錄了線程池在整個(gè)生命周期中曾經(jīng)出現(xiàn)的最大線程個(gè)數(shù)。為什么說(shuō)是曾經(jīng)呢?因?yàn)榫€程池創(chuàng)建之后,可以調(diào)用setMaximumPoolSize()改變運(yùn)行的最大線程的數(shù)目。
poolSize:
線程池中當(dāng)前線程的數(shù)量,當(dāng)該值為0的時(shí)候,意味著沒(méi)有任何線程,線程池會(huì)終止;同一時(shí)刻,poolSize不會(huì)超過(guò)maximumPoolSize。
相關(guān)實(shí)例代碼
newCachedThreadPool緩存池
/** * newCachedThreadPool線程自動(dòng)分配,不能控制上限. */ @Test public void
newCachedThreadPool() { ExecutorService cachedThreadPool =
Executors.newCachedThreadPool(); for (int i = 0; i < 20; i++) {
cachedThreadPool.execute(new Runnable() { @Override public void run() {
logger.info("cachedThreadPool測(cè)試代碼:{}", Thread.currentThread().getName()); } });
} }
newFixedThreadPool可控制上線的線程池
/** * newFixedThreadPool控制最大的線程數(shù),可以控制上限. */ @Test public void
newFixedThreadPool() { ExecutorService fixedThreadPool =
Executors.newFixedThreadPool(5); for (int i = 0; i < 20; i++) {
fixedThreadPool.execute(new Runnable() { @Override public void run() {
logger.info("fixedThreadPool測(cè)試代碼:{}", Thread.currentThread().getName()); } });
} }
newSingleThreadExecutor只有一個(gè)線程的線程池,只有當(dāng)線程出現(xiàn)異常后才會(huì)建立新的線程代替它
/** * newSingleThreadExecutor只有一個(gè)線程,當(dāng)這個(gè)線程因?yàn)楫惓=Y(jié)束,會(huì)有一個(gè)新的線程來(lái)替代它. */ @Test public
void newSingleThreadExecutor() { ExecutorService newSingleThread =
Executors.newSingleThreadExecutor(); for (int i = 0; i < 20; i++) {
newSingleThread.execute(new Runnable() { @Override public void run() {
logger.info("newSingleThread測(cè)試代碼:{}", Thread.currentThread().getName()); } });
} }
newScheduledThreadPool帶有調(diào)度功能的線程池,可以執(zhí)行周期性的任務(wù)
/** * newScheduledThreadPool按著時(shí)間間隔進(jìn)行周期性任務(wù) */ @Test public void
newScheduledThreadPool() throws InterruptedException { ScheduledExecutorService
executor = Executors.newScheduledThreadPool(5); executor.scheduleAtFixedRate(()
-> { long start = new Date().getTime(); System.out.println("scheduleAtFixedRate
開(kāi)始執(zhí)行時(shí)間:" + DateFormat.getTimeInstance().format(new Date())); try {
Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
long end = new Date().getTime(); System.out.println("scheduleAtFixedRate
執(zhí)行花費(fèi)時(shí)間=" + (end - start) / 1000 + "m"); System.out.println("scheduleAtFixedRate
執(zhí)行完成時(shí)間:" + DateFormat.getTimeInstance().format(new Date()));
System.out.println("======================================"); }, 0, 1,
TimeUnit.SECONDS);//initialDelay初始化延時(shí),period:兩次執(zhí)行最小間隔時(shí)間 Thread.sleep(1000 *
10); }
熱門(mén)工具 換一換
