java~線程池(chi)的(de)總結
線(xian)程(cheng)(cheng)的(de)(de)創建和(he)效率都(dou)需要消耗處理(li)器(qi)(cpu)的(de)(de)資源(yuan),所以我們在使(shi)用(yong)線(xian)程(cheng)(cheng)時需要注意,你的(de)(de)每一個動(dong)作都(dou)是(shi)需要為(wei)它買單的(de)(de),也(ye)正是(shi)因為(wei)線(xian)程(cheng)(cheng)的(de)(de)使(shi)用(yong)需要謹慎,所以java對線(xian)程(cheng)(cheng)的(de)(de)管理(li)也(ye)進行了封裝(zhuang),就(jiu)是(shi)今天要說的(de)(de)線(xian)程(cheng)(cheng)池(chi),目前java主要封裝(zhuang)了大概4大種類型的(de)(de)線(xian)程(cheng)(cheng)池(chi),下(xia)面簡單來介紹一下(xia)。
四大類型的線程池
- newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
- newFixedThreadPool 創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。
- newScheduledThreadPool 創建一個定長線程池,支持定時及周期性任務執行。
- newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
線程池里主要的三個參數
corePoolSize:
線程池的基本大小,即在沒有任務需要執行的時候線程池的大小,并且只有在工作隊列滿了的情況下才會創建超出這個數量的線程。這里需要注意的是:在剛剛創建ThreadPoolExecutor的時候,線程并不會立即啟動,而是要等到有任務提交時才會啟動,除非調用了prestartCoreThread/prestartAllCoreThreads事先啟動核心線程。再考慮到keepAliveTime和allowCoreThreadTimeOut超時參數的影響,所以沒有任務需要執行的時候,線程池的大小不一定是corePoolSize。
maximumPoolSize:
線程池中允許的最大線程數,線程池中的當前線程數目不會超過該值。如果隊列中任務已滿,并且當前線程個數小于maximumPoolSize,那么會創建新的線程來執行任務。這里值得一提的是largestPoolSize,該變量記錄了線程池在整個生命周期中曾經出現的最大線程個數。為什么說是曾經呢?因為線程池創建之后,可以調用setMaximumPoolSize()改變運行的最大線程的數目。
poolSize:
線(xian)(xian)程(cheng)池中當(dang)前線(xian)(xian)程(cheng)的數量,當(dang)該值為0的時(shi)候,意味著沒有任何(he)線(xian)(xian)程(cheng),線(xian)(xian)程(cheng)池會終止(zhi);同一時(shi)刻,poolSize不會超過(guo)maximumPoolSize。
相關實例代碼
newCachedThreadPool緩(huan)存池
/**
* newCachedThreadPool線程自動分配,不能控制上限.
*/
@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測試代碼:{}", Thread.currentThread().getName());
}
});
}
}
newFixedThreadPool可(ke)控制上線的線程池
/**
* newFixedThreadPool控制最大的線程數,可以控制上限.
*/
@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測試代碼:{}", Thread.currentThread().getName());
}
});
}
}
newSingleThreadExecutor只(zhi)有一個(ge)線(xian)程(cheng)的線(xian)程(cheng)池,只(zhi)有當線(xian)程(cheng)出現異常后才(cai)會建立新(xin)的線(xian)程(cheng)代替它
/**
* newSingleThreadExecutor只有一個線程,當這個線程因為異常結束,會有一個新的線程來替代它.
*/
@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測試代碼:{}", Thread.currentThread().getName());
}
});
}
}
newScheduledThreadPool帶有調度功能的(de)線(xian)程池,可以執行周期性(xing)的(de)任務
/**
* newScheduledThreadPool按著時間間隔進行周期性任務
*/
@Test
public void newScheduledThreadPool() throws InterruptedException {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
executor.scheduleAtFixedRate(() -> {
long start = new Date().getTime();
System.out.println("scheduleAtFixedRate 開始執行時間:" +
DateFormat.getTimeInstance().format(new Date()));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = new Date().getTime();
System.out.println("scheduleAtFixedRate 執行花費時間=" + (end - start) / 1000 + "m");
System.out.println("scheduleAtFixedRate 執行完成時間:" + DateFormat.getTimeInstance().format(new Date()));
System.out.println("======================================");
}, 0, 1, TimeUnit.SECONDS);//initialDelay初始化延時,period:兩次執行最小間隔時間
Thread.sleep(1000 * 10);
}