SpringBoot線程池配置使用示例詳解
一、核心特性
Springboot 集成
支持 @Async 注解,簡(jiǎn)化異步方法調(diào)用。
參數(shù)可配置化
核心線程數(shù)、最大線程數(shù)、隊(duì)列容量、拒絕策略等均可通過(guò)配置調(diào)整。
生命周期管理
實(shí)現(xiàn) Lifecycle 接口,支持線程池的啟動(dòng)和關(guān)閉(如應(yīng)用關(guān)閉時(shí)優(yōu)雅終止任務(wù))。
任務(wù)裝飾器
支持通過(guò) TaskDecorator 對(duì)任務(wù)進(jìn)行裝飾(如傳遞上下文信息)
二、添加依賴
在 pom.xml 文件中添加 Spring Boot Starter AOP 依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>三、參數(shù)詳解
通過(guò) Spring 配置文件或 @Bean 定義線程池時(shí),需設(shè)置以下關(guān)鍵參數(shù):
| 參數(shù)名稱 | 說(shuō)明 | 默認(rèn)值 |
|---|---|---|
| corePoolSize | 核心線程數(shù),即使空閑也不會(huì)被回收 | 1 |
| maxPoolSize | 最大線程數(shù),當(dāng)隊(duì)列滿時(shí)創(chuàng)建新線程直到達(dá)到此值 | Integer.MAX_VALUE |
| queueCapacity | 任務(wù)隊(duì)列容量(使用 LinkedBlockingQueue 或 ArrayBlockingQueue) | Integer.MAX_VALUE |
| keepAliveSeconds | 非核心線程的空閑存活時(shí)間(秒) | 60 |
| threadNamePrefix | 線程名前綴,便于日志追蹤 | "task-executor-" |
| allowCoreThreadTimeOut | 是否允許核心線程超時(shí)回收 | false |
| rejectedExecutionHandler | 拒絕策略(如 AbortPolicy、CallerRunsPolicy) | AbortPolicy(直接拋出異常) |
四、配置線程池
@Configuration
@EnableAsync
public class ExecutorConfig {
private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
@Value("${async.executor.thread.core_pool_size}")
private int corePoolSize;
@Value("${async.executor.thread.max_pool_size}")
private int maxPoolSize;
@Value("${async.executor.thread.queue_capacity}")
private int queueCapacity;
@Value("${async.executor.thread.name.prefix}")
private String namePrefix;
@Bean(name = "asyncServiceExecutor")
public Executor asyncServiceExecutor() {
logger.info("start asyncServiceExecutor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心線程數(shù)
executor.setCorePoolSize(corePoolSize);
//配置最大線程數(shù)
executor.setMaxPoolSize(maxPoolSize);
//配置隊(duì)列大小
executor.setQueueCapacity(queueCapacity);
//配置線程池中的線程的名稱前綴
executor.setThreadNamePrefix(namePrefix);
// rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù)
// CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是有調(diào)用者所在的線程來(lái)執(zhí)行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//執(zhí)行初始化
executor.initialize();
return executor;
}
}@Value是我配置在 application.yml,可以參考配置,自由定義
# 異步線程配置 # 配置核心線程數(shù) async.executor.thread.core_pool_size = 5 # 配置最大線程數(shù) async.executor.thread.max_pool_size = 5 # 配置隊(duì)列大小 async.executor.thread.queue_capacity = 99999 # 配置線程池中的線程的名稱前綴 async.executor.thread.name.prefix = async-service-
五、應(yīng)用實(shí)踐
1、異步任務(wù)處理
創(chuàng)建一個(gè)服務(wù)類 AsyncService,并在其方法上使用 @Async 注解來(lái)定義異步任務(wù):
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);
@Async("taskExecutor")
public void asyncTask(String taskName) {
logger.info(Thread.currentThread().getName() + " 開(kāi)始執(zhí)行任務(wù): " + taskName);
try {
Thread.sleep(2000); // 模擬耗時(shí)操作
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error("任務(wù)執(zhí)行被中斷", e);
} finally {
logger.info(Thread.currentThread().getName() + " 任務(wù)執(zhí)行完成: " + taskName);
}
}
}創(chuàng)建一個(gè)控制器類 AsyncController,用于觸發(fā)異步任務(wù)(線程安全的)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.Future;
@RestController
public class AsyncController {
private static final Logger logger = LoggerFactory.getLogger(AsyncController.class);
@Autowired
private AsyncService asyncService;
@GetMapping("/trigger")
public String triggerAsyncTasks() {
logger.info("開(kāi)始觸發(fā)異步任務(wù)");
for (int i = 0; i < 10; i++) {
asyncService.asyncTask("任務(wù) " + i);
}
return "異步任務(wù)已觸發(fā)";
}
}創(chuàng)建一個(gè)監(jiān)控組件 ThreadPoolMonitor,用于定期監(jiān)控線程池的狀態(tài)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ThreadPoolMonitor {
private static final Logger logger = LoggerFactory.getLogger(ThreadPoolMonitor.class);
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Scheduled(fixedRate = 60000) // 每分鐘執(zhí)行一次
public void monitorThreadPool() {
int activeCount = taskExecutor.getActiveCount();
int poolSize = taskExecutor.getPoolSize();
int corePoolSize = taskExecutor.getCorePoolSize();
int maxPoolSize = taskExecutor.getMaxPoolSize();
int queueSize = taskExecutor.getThreadPoolExecutor().getQueue().size();
int completedTaskCount = taskExecutor.getThreadPoolExecutor().getCompletedTaskCount();
logger.info("線程池狀態(tài) - 活動(dòng)線程數(shù): {}, 當(dāng)前線程數(shù): {}, 核心線程數(shù): {}, 最大線程數(shù): {}, 隊(duì)列大小: {}, 已完成任務(wù)數(shù): {}",
activeCount, poolSize, corePoolSize, maxPoolSize, queueSize, completedTaskCount);
// 檢查線程池是否接近飽和
if (activeCount >= maxPoolSize * 0.8 || queueSize >= taskExecutor.getQueueCapacity() * 0.8) {
logger.warn("線程池負(fù)載過(guò)高!請(qǐng)考慮優(yōu)化配置或檢查任務(wù)執(zhí)行情況");
}
}
} 確保在啟動(dòng)類上添加 @EnableAsync 注解,以啟用異步任務(wù)支持
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class AsyncDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncDemoApplication.class, args);
}
}測(cè)試:
啟動(dòng) Spring Boot 應(yīng)用后,訪問(wèn) http://localhost:8080/trigger,即可看到異步任務(wù)在線程池中執(zhí)行的情況,同時(shí)線程池的狀態(tài)也會(huì)定期輸出到日志中。
代碼說(shuō)明
@EnableAsync 注解 :用于啟用 Spring 的異步方法執(zhí)行支持,確保 Spring 容器能夠識(shí)別和處理帶有
@Async注解的方法。@Async 注解 :用于標(biāo)注希望異步執(zhí)行的方法,需指定所使用的線程池 Bean 的名稱,在本例中為 “taskExecutor”。當(dāng)該方法被調(diào)用時(shí),Spring 會(huì)將其提交到指定的線程池中執(zhí)行。
ThreadPoolTaskExecutor :是 Spring 提供的一個(gè)線程池任務(wù)執(zhí)行器,通過(guò)設(shè)置核心線程數(shù)、最大線程數(shù)、隊(duì)列容量等參數(shù),可以根據(jù)應(yīng)用的需求靈活地配置線程池。
異步任務(wù)失敗處理 :通過(guò)自定義的拒絕策略,在線程池滿時(shí)記錄詳細(xì)信息并拋出異常,以便及時(shí)發(fā)現(xiàn)任務(wù)執(zhí)行失敗的情況。
線程池監(jiān)控 :使用
@Scheduled注解定期監(jiān)控線程池的狀態(tài),包括活動(dòng)線程數(shù)、當(dāng)前線程數(shù)、核心線程數(shù)、最大線程數(shù)、隊(duì)列大小和已完成任務(wù)數(shù)等,幫助開(kāi)發(fā)者了解線程池的運(yùn)行情況,以便及時(shí)進(jìn)行優(yōu)化和調(diào)整
2、高并發(fā)請(qǐng)求處理
在 Web 應(yīng)用中處理大量并發(fā)請(qǐng)求,避免阻塞主線程
@RestController
public class MyController {
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@GetMapping("/process")
public CompletableFuture<String> handleRequest() {
return CompletableFuture.supplyAsync(() -> {
// 耗時(shí)操作
return "Result";
}, taskExecutor);
}
}3、定時(shí)任務(wù)調(diào)度
@EnableScheduling
@Configuration
public class SchedulerConfig {
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5);
scheduler.setThreadNamePrefix("Scheduler-");
return scheduler;
}
}
@Service
public class ScheduledService {
@Scheduled(fixedRate = 5000)
public void scheduledTask() {
// 定時(shí)任務(wù)邏輯
}
}拒絕策略(Rejected Policies)
當(dāng)線程池和隊(duì)列均滿時(shí),處理新任務(wù)的策略:
| 策略類 | 行為描述 |
|---|---|
| AbortPolicy | 直接拋出 RejectedExecutionException(默認(rèn)) |
| CallerRunsPolicy | 由提交任務(wù)的線程直接執(zhí)行任務(wù)(同步阻塞提交者) |
| DiscardPolicy | 靜默丟棄新任務(wù),不拋異常 |
| DiscardOldestPolicy | 丟棄隊(duì)列中最舊的任務(wù),然后重試提交新任務(wù) |
如下給出不同拒絕策略的配置類,請(qǐng)結(jié)合上面的配置類整合使用
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Configuration
public class ThreadPoolConfig {
@Bean(name = "abortPolicyExecutor")
public ThreadPoolTaskExecutor abortPolicyExecutor() {
return createExecutor(new ThreadPoolExecutor.AbortPolicy());
}
@Bean(name = "callerRunsPolicyExecutor")
public ThreadPoolTaskExecutor callerRunsPolicyExecutor() {
return createExecutor(new ThreadPoolExecutor.CallerRunsPolicy());
}
@Bean(name = "discardPolicyExecutor")
public ThreadPoolTaskExecutor discardPolicyExecutor() {
return createExecutor(new ThreadPoolExecutor.DiscardPolicy());
}
@Bean(name = "discardOldestPolicyExecutor")
public ThreadPoolTaskExecutor discardOldestPolicyExecutor() {
return createExecutor(new ThreadPoolExecutor.DiscardOldestPolicy());
}
private ThreadPoolTaskExecutor createExecutor(ThreadPoolExecutor.RejectedExecutionHandler rejectedExecutionHandler) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 核心線程數(shù)
executor.setMaxPoolSize(10); // 最大線程數(shù)
executor.setQueueCapacity(100); // 隊(duì)列容量
executor.setThreadNamePrefix("Task-Executor-"); // 線程名前綴
executor.setRejectedExecutionHandler(rejectedExecutionHandler);
executor.initialize();
return executor;
}
}創(chuàng)建一個(gè)服務(wù)類 TaskService,用于執(zhí)行任務(wù)
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class TaskService {
@Async("abortPolicyExecutor")
public void executeWithAbortPolicy(String taskName) {
executeTask(taskName);
}
@Async("callerRunsPolicyExecutor")
public void executeWithCallerRunsPolicy(String taskName) {
executeTask(taskName);
}
@Async("discardPolicyExecutor")
public void executeWithDiscardPolicy(String taskName) {
executeTask(taskName);
}
@Async("discardOldestPolicyExecutor")
public void executeWithDiscardOldestPolicy(String taskName) {
executeTask(taskName);
}
private void executeTask(String taskName) {
try {
System.out.println(Thread.currentThread().getName() + " 開(kāi)始執(zhí)行任務(wù): " + taskName);
Thread.sleep(2000); // 模擬任務(wù)執(zhí)行時(shí)間
System.out.println(Thread.currentThread().getName() + " 任務(wù)執(zhí)行完成: " + taskName);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("任務(wù)執(zhí)行被中斷: " + taskName);
}
}
}創(chuàng)建一個(gè)控制器類 TaskController,用于觸發(fā)任務(wù)執(zhí)行
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TaskController {
@Autowired
private TaskService taskService;
@GetMapping("/trigger/abort")
public String triggerAbortPolicy(@RequestParam String taskName) {
taskService.executeWithAbortPolicy(taskName);
return "任務(wù)已提交到使用 AbortPolicy 的線程池";
}
@GetMapping("/trigger/caller")
public String triggerCallerRunsPolicy(@RequestParam String taskName) {
taskService.executeWithCallerRunsPolicy(taskName);
return "任務(wù)已提交到使用 CallerRunsPolicy 的線程池";
}
@GetMapping("/trigger/discard")
public String triggerDiscardPolicy(@RequestParam String taskName) {
taskService.executeWithDiscardPolicy(taskName);
return "任務(wù)已提交到使用 DiscardPolicy 的線程池";
}
@GetMapping("/trigger/discardoldest")
public String triggerDiscardOldestPolicy(@RequestParam String taskName) {
taskService.executeWithDiscardOldestPolicy(taskName);
return "任務(wù)已提交到使用 DiscardOldestPolicy 的線程池";
}
}啟動(dòng) Spring Boot 應(yīng)用后,分別訪問(wèn)以下 URL 來(lái)測(cè)試不同拒絕策略的行為:
http://localhost:8080/trigger/abort?taskName=任務(wù)1http://localhost:8080/trigger/caller?taskName=任務(wù)2http://localhost:8080/trigger/discard?taskName=任務(wù)3http://localhost:8080/trigger/discardoldest?taskName=任務(wù)4代碼說(shuō)明
線程池配置:
使用
ThreadPoolTaskExecutor創(chuàng)建線程池。配置了 4 個(gè)不同的線程池,每個(gè)線程池使用不同的拒絕策略。
每個(gè)線程池的核心線程數(shù)為 5,最大線程數(shù)為 10,隊(duì)列容量為 100。
拒絕策略:
AbortPolicy:直接拋出
RejectedExecutionException。CallerRunsPolicy:由提交任務(wù)的線程直接執(zhí)行任務(wù)。
DiscardPolicy:靜默丟棄新任務(wù),不拋異常。
DiscardOldestPolicy:丟棄隊(duì)列中最舊的任務(wù),然后重試提交新任務(wù)。
任務(wù)執(zhí)行:
TaskService類中的每個(gè)方法都使用@Async注解,并指定使用的線程池。executeTask方法模擬任務(wù)執(zhí)行,包含一個(gè) 2 秒的睡眠時(shí)間。通過(guò)這個(gè)示例,你可以觀察不同拒絕策略在任務(wù)被拒絕時(shí)的行為。例如,當(dāng)線程池滿時(shí),
AbortPolicy會(huì)拋出異常,CallerRunsPolicy會(huì)讓提交任務(wù)的線程執(zhí)行任務(wù),DiscardPolicy會(huì)靜默丟棄任務(wù),而DiscardOldestPolicy會(huì)丟棄最舊的任務(wù)并嘗試提交新任務(wù)
6、最佳配置
· 合理設(shè)置線程池參數(shù)
CPU 密集型任務(wù):核心線程數(shù) ≈ CPU 核心數(shù)
I/O 密集型任務(wù):核心線程數(shù) ≈ CPU 核心數(shù) * 2,并增大隊(duì)列容量。
· 避免隊(duì)列無(wú)限堆積
設(shè)置合理的 queueCapacity,防止內(nèi)存溢出(OOM)。
· 統(tǒng)一異常處理
通過(guò) AsyncUncaughtExceptionHandler 捕獲異步任務(wù)中的異常:@Configuration public class AsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // ... 配置參數(shù) return executor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (ex, method, params) -> { // 處理異常 }; } }應(yīng)用退出時(shí),調(diào)用 shutdown() 并等待剩余任務(wù)執(zhí)行完畢
executor.shutdown(); try { if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { executor.shutdownNow(); } } catch (InterruptedException e) { executor.shutdownNow(); }總結(jié):
ThreadPoolTaskExecutor 是 Spring 生態(tài)中管理線程任務(wù)的利器,通過(guò)靈活的配置和與 Spring 的無(wú)縫集成,能夠高效處理異步任務(wù)、高并發(fā)請(qǐng)求和定時(shí)調(diào)度。合理設(shè)置參數(shù)、選擇拒絕策略,并結(jié)合監(jiān)控手段,可顯著提升系統(tǒng)性能和穩(wěn)定性。
到此這篇關(guān)于SpringBoot線程池配置使用詳解的文章就介紹到這了,更多相關(guān)SpringBoot線程池配置使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中在控制臺(tái)讀取字符的實(shí)現(xiàn)示例
Scanner是Java中的一個(gè)類,可以用于讀取控制臺(tái)輸入,通過(guò)Scanner對(duì)象可以方便地從控制臺(tái)讀取數(shù)字或字符串,本文就來(lái)介紹一下Java中在控制臺(tái)讀取字符的實(shí)現(xiàn)示例,感興趣的可以了解一下2023-10-10
nginx代理模式下java獲取客戶端真實(shí)ip地址實(shí)例代碼
在web開(kāi)發(fā)中,獲取客戶端真實(shí)ip是常見(jiàn)需求,但在反向代理(如nginx)環(huán)境下,直接通過(guò)request.getremoteaddr()獲取的可能是代理服務(wù)器ip而非真實(shí)客戶端ip,這篇文章主要介紹了nginx代理模式下java獲取客戶端真實(shí)ip地址的相關(guān)資料,需要的朋友可以參考下2026-04-04
詳解Java編寫算法時(shí)如何加快讀寫數(shù)據(jù)速度
這篇文章主要為大家詳細(xì)介紹了Java在編寫算法時(shí)如何加快讀寫數(shù)據(jù)速度,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
SpringBoot的自動(dòng)裝配機(jī)制和Starter的實(shí)現(xiàn)原理分析
SpringBoot自動(dòng)裝配機(jī)制通過(guò)`@EnableAutoConfiguration`開(kāi)啟,基于條件化配置實(shí)現(xiàn),簡(jiǎn)化開(kāi)發(fā),Starter作為“開(kāi)箱即用”的依賴模塊,包含庫(kù)依賴、自動(dòng)配置類和附加配置,自動(dòng)裝配與Starter結(jié)合,用戶只需引入Starter即可獲得完整功能,提升開(kāi)發(fā)效率2026-05-05
Java實(shí)現(xiàn)一鍵將Word文檔轉(zhuǎn)為PDF的兩種方法
本文主要介紹了Java實(shí)現(xiàn)一鍵將Word文檔轉(zhuǎn)為PDF的兩種方法,分別使用Apache POI和Docx4J結(jié)合iText庫(kù)來(lái)實(shí)現(xiàn)Word轉(zhuǎn)PDF,具有一定的參考價(jià)值,感興趣的可以了解一下2025-04-04
springboot 使用poi進(jìn)行數(shù)據(jù)的導(dǎo)出過(guò)程詳解
這篇文章主要介紹了springboot 使用poi進(jìn)行數(shù)據(jù)的導(dǎo)出過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
SpringBoot項(xiàng)目中JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理的使用詳解
JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理都是SpringBoot中實(shí)現(xiàn)AOP的重要技術(shù),JDK動(dòng)態(tài)代理通過(guò)反射生成代理類,適用于目標(biāo)類實(shí)現(xiàn)了接口的場(chǎng)景,性能較好,易用性高,但必須實(shí)現(xiàn)接口且不能代理final方法,CGLIB動(dòng)態(tài)代理通過(guò)生成子類實(shí)現(xiàn)代理2025-03-03

