Java線程池核心參數(shù)原理及使用指南
一、線程池概述
1.1 什么是線程池
線程池是一種多線程處理形式,它維護(hù)著一個(gè)線程隊(duì)列,等待監(jiān)督管理者分配可并發(fā)執(zhí)行的任務(wù)。通過線程池可以避免頻繁創(chuàng)建和銷毀線程帶來的性能開銷。
1.2 線程池的優(yōu)勢
- 降低資源消耗:重復(fù)利用已創(chuàng)建的線程,減少線程創(chuàng)建和銷毀的開銷
- 提高響應(yīng)速度:任務(wù)到達(dá)時(shí),無需等待線程創(chuàng)建即可立即執(zhí)行
- 提高線程的可管理性:統(tǒng)一分配、調(diào)優(yōu)和監(jiān)控線程
- 提供更強(qiáng)大的功能:支持定時(shí)執(zhí)行、定期執(zhí)行等功能
二、線程池核心類
Java線程池主要通過java.util.concurrent包下的以下類實(shí)現(xiàn):
// 主要接口和類 Executor // 執(zhí)行器接口 ExecutorService // 執(zhí)行服務(wù)接口 ThreadPoolExecutor // 線程池核心實(shí)現(xiàn)類 ScheduledThreadPoolExecutor // 支持定時(shí)調(diào)度的線程池 Executors // 線程池工廠類
三、ThreadPoolExecutor核心參數(shù)詳解
3.1 構(gòu)造方法
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
)3.2 七大核心參數(shù)
1.corePoolSize(核心線程數(shù))
- 線程池中保持存活的線程數(shù)量(即使空閑)
- 默認(rèn)情況下,核心線程不會(huì)超時(shí)被回收
- 可以通過
allowCoreThreadTimeOut(true)設(shè)置核心線程超時(shí)
2.maximumPoolSize(最大線程數(shù))
- 線程池允許創(chuàng)建的最大線程數(shù)量
- 當(dāng)工作隊(duì)列滿且當(dāng)前線程數(shù)小于最大線程數(shù)時(shí),會(huì)創(chuàng)建新線程
3.keepAliveTime(線程空閑時(shí)間)
- 非核心線程空閑時(shí)的存活時(shí)間
- 當(dāng)線程空閑時(shí)間超過該值且當(dāng)前線程數(shù)大于核心線程數(shù)時(shí),線程會(huì)被回收
4.unit(時(shí)間單位)
- keepAliveTime的時(shí)間單位
- 如:TimeUnit.SECONDS、TimeUnit.MILLISECONDS
5.workQueue(工作隊(duì)列)
常見的工作隊(duì)列實(shí)現(xiàn):
| 隊(duì)列類型 | 說明 | 特點(diǎn) |
|---|---|---|
| ArrayBlockingQueue | 有界隊(duì)列 | 固定大小,F(xiàn)IFO |
| LinkedBlockingQueue | 無界隊(duì)列(默認(rèn)) | 容量為Integer.MAX_VALUE |
| SynchronousQueue | 同步隊(duì)列 | 不存儲(chǔ)元素,每個(gè)插入操作必須等待另一個(gè)線程的移除操作 |
| PriorityBlockingQueue | 優(yōu)先級(jí)隊(duì)列 | 具有優(yōu)先級(jí)的無界阻塞隊(duì)列 |
6.threadFactory(線程工廠)
- 用于創(chuàng)建新線程
- 可以設(shè)置線程名稱、優(yōu)先級(jí)、守護(hù)線程等屬性
// 自定義線程工廠示例
ThreadFactory customThreadFactory = new ThreadFactory() {
private final AtomicInteger threadNumber = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("MyThread-" + threadNumber.getAndIncrement());
thread.setDaemon(false);
thread.setPriority(Thread.NORM_PRIORITY);
return thread;
}
};7.handler(拒絕策略)
當(dāng)線程池和工作隊(duì)列都滿時(shí),對(duì)新任務(wù)的處理策略:
| 拒絕策略 | 說明 |
|---|---|
| AbortPolicy(默認(rèn)) | 拋出RejectedExecutionException異常 |
| CallerRunsPolicy | 由調(diào)用線程(提交任務(wù)的線程)執(zhí)行該任務(wù) |
| DiscardPolicy | 直接丟棄任務(wù),不拋異常 |
| DiscardOldestPolicy | 丟棄隊(duì)列中最舊的任務(wù),然后嘗試提交新任務(wù) |
四、線程池工作原理
4.1 任務(wù)處理流程
// 線程池工作流程偽代碼
public void execute(Runnable task) {
if (當(dāng)前線程數(shù) < corePoolSize) {
創(chuàng)建新線程執(zhí)行任務(wù);
} else if (工作隊(duì)列未滿) {
將任務(wù)加入工作隊(duì)列;
} else if (當(dāng)前線程數(shù) < maximumPoolSize) {
創(chuàng)建新線程執(zhí)行任務(wù);
} else {
執(zhí)行拒絕策略;
}
}4.2 狀態(tài)流轉(zhuǎn)圖
任務(wù)提交
↓
當(dāng)前線程數(shù) < corePoolSize? → 是 → 創(chuàng)建核心線程執(zhí)行
↓否
工作隊(duì)列未滿? → 是 → 任務(wù)入隊(duì)等待
↓否
當(dāng)前線程數(shù) < maximumPoolSize? → 是 → 創(chuàng)建非核心線程執(zhí)行
↓否
執(zhí)行拒絕策略五、常見線程池類型
5.1 通過Executors創(chuàng)建的線程池(不建議使用)
原因:阿里為何禁止使用Executors去創(chuàng)建線程池
// 1. 固定大小線程池 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10); // 特點(diǎn):核心線程數(shù)=最大線程數(shù),使用無界隊(duì)列 // 2. 單線程線程池 ExecutorService singleThreadPool = Executors.newSingleThreadExecutor(); // 特點(diǎn):只有一個(gè)線程,任務(wù)順序執(zhí)行 // 3. 緩存線程池 ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); // 特點(diǎn):核心線程數(shù)為0,最大線程數(shù)為Integer.MAX_VALUE,使用同步隊(duì)列 // 4. 定時(shí)任務(wù)線程池 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); // 支持定時(shí)和周期性任務(wù)
5.2 創(chuàng)建自定義線程池(推薦)
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // corePoolSize
10, // maximumPoolSize
60L, // keepAliveTime
TimeUnit.SECONDS, // unit
new ArrayBlockingQueue<>(100), // workQueue
Executors.defaultThreadFactory(), // threadFactory
new ThreadPoolExecutor.AbortPolicy() // handler
);六、線程池使用示例
public class ThreadPoolExample {
public static void main(String[] args) {
// 創(chuàng)建線程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 5, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
new CustomThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 提交任務(wù)
for (int i = 1; i <= 20; i++) {
final int taskId = i;
executor.execute(() -> {
System.out.println(Thread.currentThread().getName() +
" 執(zhí)行任務(wù) " + taskId);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// 監(jiān)控線程池狀態(tài)
monitorThreadPool(executor);
// 優(yōu)雅關(guān)閉
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
// 自定義線程工廠
static class CustomThreadFactory implements ThreadFactory {
private final AtomicInteger counter = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("CustomThread-" + counter.getAndIncrement());
thread.setDaemon(false);
thread.setPriority(Thread.NORM_PRIORITY);
return thread;
}
}
// 監(jiān)控線程池狀態(tài)
private static void monitorThreadPool(ThreadPoolExecutor executor) {
new Thread(() -> {
while (!executor.isTerminated()) {
System.out.println("=== 線程池狀態(tài)監(jiān)控 ===");
System.out.println("核心線程數(shù): " + executor.getCorePoolSize());
System.out.println("當(dāng)前線程數(shù): " + executor.getPoolSize());
System.out.println("活躍線程數(shù): " + executor.getActiveCount());
System.out.println("隊(duì)列大小: " + executor.getQueue().size());
System.out.println("完成任務(wù)數(shù): " + executor.getCompletedTaskCount());
System.out.println("總?cè)蝿?wù)數(shù): " + executor.getTaskCount());
System.out.println("========================\n");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}).start();
}
}七、最佳實(shí)踐與注意事項(xiàng)
7.1 線程池配置建議
CPU密集型任務(wù)
// 線程數(shù) ≈ CPU核心數(shù) + 1 int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
IO密集型任務(wù)
// 線程數(shù) ≈ CPU核心數(shù) * 2 // 或根據(jù)具體IO等待時(shí)間調(diào)整 int corePoolSize = Runtime.getRuntime().availableProcessors() * 2;
7.2 注意事項(xiàng)
- 避免使用無界隊(duì)列:可能導(dǎo)致內(nèi)存溢出
- 合理設(shè)置拒絕策略:根據(jù)業(yè)務(wù)需求選擇
- 優(yōu)雅關(guān)閉線程池:使用shutdown()和shutdownNow()
- 監(jiān)控線程池狀態(tài):定期檢查線程池運(yùn)行狀況
- 為線程命名:便于問題排查
7.3 線程池參數(shù)動(dòng)態(tài)調(diào)整
// Java 1.7+ 支持動(dòng)態(tài)調(diào)整參數(shù) executor.setCorePoolSize(10); executor.setMaximumPoolSize(20); executor.setKeepAliveTime(120, TimeUnit.SECONDS);
八、總結(jié)
Java線程池是并發(fā)編程的核心組件,合理配置線程池參數(shù)對(duì)系統(tǒng)性能有重要影響。理解每個(gè)參數(shù)的含義和工作原理,根據(jù)實(shí)際業(yè)務(wù)場景選擇合適的配置,是高效使用線程池的關(guān)鍵。在實(shí)際開發(fā)中,推薦使用ThreadPoolExecutor手動(dòng)創(chuàng)建線程池,而不是使用Executors的快捷方法,以便更好地控制線程池的行為。
到此這篇關(guān)于Java線程池核心參數(shù)原理及使用指南的文章就介紹到這了,更多相關(guān)java線程池參數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatisplus集成springboot完成分頁查詢功能(示例代碼)
今天小編給大家分享Mybatisplus集成springboot完成分頁查詢功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-11-11
Java reservedcodecachesize虛擬機(jī)參數(shù)案例詳解
這篇文章主要介紹了Java reservedcodecachesize虛擬機(jī)參數(shù)案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Java關(guān)鍵字volatile和synchronized作用和區(qū)別
這篇文章主要為大家詳細(xì)介紹了Java關(guān)鍵字volatile和synchronized的作用和區(qū)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
Spring?Boot?整合?Fisco?Bcos部署、調(diào)用區(qū)塊鏈合約的案例
本篇文章介紹?Spring?Boot?整合?Fisco?Bcos?的相關(guān)技術(shù),最最重要的技術(shù)點(diǎn),部署、調(diào)用區(qū)塊鏈合約的工程案例,本文通過流程分析給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-01-01
Mybatis-Plus3.2.0 MetaObjectHandler 無法進(jìn)行公共字段全局填充
這篇文章主要介紹了Mybatis-Plus3.2.0 MetaObjectHandler 無法進(jìn)行公共字段全局填充,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11

