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

