文章轉(zhuǎn)載自:https://blog.csdn.net/qq_36226120/article/details/81866801
一、概述
New Thread的弊端如下:
a、每次New Thread新建對(duì)象性能差。
b、線程缺乏統(tǒng)一的管理,可能無(wú)限制的新建線程,相互之間競(jìng)爭(zhēng),極可能占用過(guò)多的系統(tǒng)資源導(dǎo)致死機(jī) 或者 OOM。
c、缺乏更多功能,如定時(shí)執(zhí)行、定期執(zhí)行、線程中斷。
Java提供的四種線程池的好處在于:
a、重用存在的線程,減少對(duì)象創(chuàng)建、消亡的開(kāi)銷,性能佳。
b、可有效控制最大并發(fā)線程數(shù)、提供系統(tǒng)資源的使用率,同時(shí)避免過(guò)多資源競(jìng)爭(zhēng),避免堵塞。
c、提供定時(shí)執(zhí)行、定期執(zhí)行、單線程、并發(fā)數(shù)控制等功能。
二、Executors 創(chuàng)建線程池
Java通過(guò)Executors提供四種線程池,分別為:
newCachedThreadPool創(chuàng)建一個(gè)可緩存線程池,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程,若無(wú)可回收,則新建線程。
newFixedThreadPool創(chuàng)建一個(gè)定長(zhǎng)線程池,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待,表示同一時(shí)刻只能有這么大的并發(fā)數(shù)
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í)行。

三、ThreadPoolExecutor 創(chuàng)建線程池
線程池不建議使用Executors去創(chuàng)建:
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
而是通過(guò)ThreadPoolExecutor的方式,這樣的處理方式讓寫的同學(xué)更加明確線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。 說(shuō)明:Executors各個(gè)方法的弊端:
1、newFixedThreadPool和newSingleThreadExecutor:
?? 主要問(wèn)題是堆積的請(qǐng)求處理隊(duì)列可能會(huì)耗費(fèi)非常大的內(nèi)存,甚至OOM。
2、newCachedThreadPool和newScheduledThreadPool:
?? 主要問(wèn)題是線程數(shù)最大數(shù)是Integer.MAX_VALUE,可能會(huì)創(chuàng)建數(shù)量非常多的線程,甚至OOM。
這里介紹三種創(chuàng)建線程池的方式:
Example 1:
// org.apache.commons.lang3.concurrent.BasicThreadFactory
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
Example 2:
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
//Common Thread Pool
ExecutorService pool = new ThreadPoolExecutor(5, 200,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
pool.execute(()-> System.out.println(Thread.currentThread().getName()));
pool.shutdown();//gracefully shutdown
Example 3:
<bean id="userThreadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="queueCapacity" value="2000" />
<property name="threadFactory" value= threadFactory />
<property name="rejectedExecutionHandler">
<ref local="rejectedExecutionHandler" />
</property>
</bean>
//in code
userThreadPool.execute(thread);
例子:
public class ThreadPoolHelper {
private static final Logger logger = Logger.getLogger(ThreadPoolHelper.class);
private static final int POOL_SIZE = 40;//線程池大小
//訂單任務(wù)線程池
private static ThreadPoolExecutor comitTaskPool =(ThreadPoolExecutor) new ScheduledThreadPoolExecutor(POOL_SIZE,
new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
/**
* 執(zhí)行訂單任務(wù)
*
* @param comitTask
*/
public static void executeTask(Runnable comitTask) {
comitTaskPool.execute(comitTask);
logger.debug("【線程池任務(wù)】線程池中線程數(shù):" + comitTaskPool.getPoolSize());
logger.debug("【線程池任務(wù)】隊(duì)列中等待執(zhí)行的任務(wù)數(shù):" + comitTaskPool.getQueue().size());
logger.debug("【線程池任務(wù)】已執(zhí)行完任務(wù)數(shù):" + comitTaskPool.getCompletedTaskCount());
}
/**
* 關(guān)閉線程池
*/
public static void shutdown() {
logger.debug("shutdown comitTaskPool...");
comitTaskPool.shutdown();
try {
if (!comitTaskPool.isTerminated()) {
logger.debug("直接關(guān)閉失敗[" + comitTaskPool.toString() + "]");
comitTaskPool.awaitTermination(3, TimeUnit.SECONDS);
if (comitTaskPool.isTerminated()) {
logger.debug("成功關(guān)閉[" + comitTaskPool.toString() + "]");
} else {
logger.debug("[" + comitTaskPool.toString() + "]關(guān)閉失敗,執(zhí)行shutdownNow...");
if (comitTaskPool.shutdownNow().size() > 0) {
logger.debug("[" + comitTaskPool.toString() + "]沒(méi)有關(guān)閉成功");
} else {
logger.debug("shutdownNow執(zhí)行完畢,成功關(guān)閉[" + comitTaskPool.toString() + "]");
}
}
} else {
logger.debug("成功關(guān)閉[" + comitTaskPool.toString() + "]");
}
} catch (InterruptedException e) {
logger.warn("接收到中斷請(qǐng)" + comitTaskPool.toString() + "停止操作");
}
}
}
定時(shí)任務(wù):
ScheduledFuture<?> scheduleAtFixedRate?(Runnable command,
long initialDelay,
long period,
TimeUnit unit)
//command - 要執(zhí)行的任務(wù)
//initialDelay - 延遲第一次執(zhí)行的時(shí)間
//period - 連續(xù)執(zhí)行之間的時(shí)期
//unit - initialDelay和period參數(shù)的時(shí)間單位
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor (1,
new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
executorService.scheduleAtFixedRate(() -> {
//執(zhí)行的任務(wù)
},1000,5000, TimeUnit.HOURS);