當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
SpringBoot 自定义线程池
生活随笔
收集整理的這篇文章主要介紹了
SpringBoot 自定义线程池
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 一、自定義線程池
- 1. yml配置
- 2. 線程池配置屬性類
- 3. 開啟異步線程支持
- 4. 創建自定義線程池配置類
- 5. service邏輯層
- 6. controller控制層
- 7. 效果圖
- 二、配置默認線程池
- 2.1. yml
- 2.2.線程池配置屬性類
- 2.3. 開啟異步線程支持
- 2.4. 裝配線程池
- 2.5. service邏輯層
- 2.6. controller控制層
- 2.7. 效果圖
自定義線程池有2種方法:
第一種:是自定義線程池,使用時指定線程池名稱,執行異步任務。
第二種:重寫spring默認線程池,然后使用自己重寫后的線程池,執行異步任務。
一、自定義線程池
1. yml配置
# 線程池配置參數 task:pool:corePoolSize: 10 # 設置核心線程數maxPoolSize: 20 # 設置最大線程數keepAliveTime: 300 # 設置空閑線程存活時間(秒)queueCapacity: 100 # 設置隊列容量threadNamePrefix: "gblfy-signpolicy-asynnotify-" # 設置線程名稱前綴awaitTerminationSeconds: 60 # 設置線程池等待終止時間(秒) spring:main:allow-bean-definition-overriding: true2. 線程池配置屬性類
package com.gblfy.config;import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties;/*** 線程配置屬性類** @Author gblfy* @Date 2022-04-05 17:20**/ @Data @ConfigurationProperties(prefix = "task.pool") public class TaskThreadPoolConfig {private int corePoolSize;private int maxPoolSize;private int keepAliveSeconds;private int queueCapacity;private int awaitTerminationSeconds;private String threadNamePrefix; }3. 開啟異步線程支持
在啟動類上/開啟異步線程支持+開啟配置屬性支持
package com.gblfy;import com.gblfy.config.TaskThreadPoolConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.scheduling.annotation.EnableAsync;@EnableAsync//開啟異步線程支持 @EnableConfigurationProperties({TaskThreadPoolConfig.class})//開啟配置屬性支持 @SpringBootApplication public class AsyncThreadApplication {public static void main(String[] args) {SpringApplication.run(AsyncThreadApplication.class, args);}}4. 創建自定義線程池配置類
package com.gblfy.config;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component;import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor;/*** 創建自定義線程池配置類** @Author gblfy* @Date 2022-04-05 17:26**/ @Configuration public class AsyncScheduledTaskConfig {@Autowiredprivate TaskThreadPoolConfig config;/*** 1.這種形式的線程池配置是需要在使用的方法上面添加@Async("customAsyncThreadPool")注解的* 2。如果在使用的方法上不添加該注解,那么spring就會使用默認的線程池* 3.所以如果添加@Async注解但是不指定使用的線程池,又想自己自定義線程池,那么就可以重寫spring默認的線程池* 4.所以第二個方法就是重寫spring默認的線程池** @return*/@Bean("customAsyncThreadPool")public Executor customAsyncThreadPool() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//最大線程數executor.setMaxPoolSize(config.getMaxPoolSize());//核心線程數executor.setCorePoolSize(config.getCorePoolSize());//任務隊列的大小executor.setQueueCapacity(config.getQueueCapacity());//線程池名的前綴executor.setThreadNamePrefix(config.getThreadNamePrefix());//允許線程的空閑時間30秒executor.setKeepAliveSeconds(config.getKeepAliveSeconds());//設置線程池關閉的時候等待所有任務都完成再繼續銷毀其他的Beanexecutor.setWaitForTasksToCompleteOnShutdown(true);//設置線程池中任務的等待時間,如果超過這個時候還沒有銷毀就強制銷毀,以確保應用最后能夠被關閉,而不是阻塞住executor.setAwaitTerminationSeconds(config.getAwaitTerminationSeconds());/*** 拒絕處理策略* CallerRunsPolicy():交由調用方線程運行,比如 main 線程。* AbortPolicy():直接拋出異常。* DiscardPolicy():直接丟棄。* DiscardOldestPolicy():丟棄隊列中最老的任務。*//*** 特殊說明:* 1. 這里演示環境,拒絕策略咱們采用拋出異常* 2.真實業務場景會把緩存隊列的大小會設置大一些,* 如果,提交的任務數量超過最大線程數量或將任務環緩存到本地、redis、mysql中,保證消息不丟失* 3.如果項目比較大的話,異步通知種類很多的話,建議采用MQ做異步通知方案*/executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//線程初始化executor.initialize();return executor;} }5. service邏輯層
package com.gblfy.service;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;/*** 自定義線程池測試1** @Author gblfy* @Date 2022-04-05 17:55**/ @Service public class ThreadPoolService {private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolService.class);@Async("customAsyncThreadPool")//指定使用哪個線程池配置,不然會使用spring默認的線程池public void executeAsync() {System.out.println("executeAsync");LOGGER.info("當前運行線程名稱:{}", Thread.currentThread().getName());} } package com.gblfy.service;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;/*** 自定義線程池測試2** @Author gblfy* @Date 2022-04-05 17:55**/ @Service public class ThreadPoolService2 {private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolService2.class);@Async("customAsyncThreadPool")//指定使用哪個線程池配置,不然會使用spring默認的線程池public void executeAsync() {System.out.println("executeAsync2");LOGGER.info("當前運行線程名稱:{}", Thread.currentThread().getName());} }6. controller控制層
package com.gblfy.controller;import com.gblfy.service.ThreadPoolService; import com.gblfy.service.ThreadPoolService2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;/*** 自定義線程池側是** @Author gblfy* @Date 2022-04-05 17:54**/ @RestController public class ThreadPoolController {@Autowiredprivate ThreadPoolService threadPoolService;@Autowiredprivate ThreadPoolService2 threadPoolService2;@GetMapping("/threadPoolTest")public void threadPoolTest() {threadPoolService.executeAsync();threadPoolService2.executeAsync();} }7. 效果圖
瀏覽器請求:http://localhost:8080/threadPoolTest
二、配置默認線程池
第一種線程池配置是需要在使用的方法上面添加@Async(“customAsyncThreadPool”)注解的。
而這種方式是重寫spring默認的線程池,使用的方法上面添加@Async注解,不用去聲明線程池類
2.1. yml
# 線程池配置參數 task:pool:corePoolSize: 10 # 設置核心線程數maxPoolSize: 20 # 設置最大線程數keepAliveTime: 300 # 設置空閑線程存活時間(秒)queueCapacity: 100 # 設置隊列容量threadNamePrefix: "gblfy-signpolicy-asynnotify-" # 設置線程名稱前綴awaitTerminationSeconds: 60 # 設置線程池等待終止時間(秒) spring:main:allow-bean-definition-overriding: true2.2.線程池配置屬性類
package com.gblfy.config;import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties;/*** 線程配置屬性類** @Author gblfy* @Date 2022-04-05 17:20**/ @Data @ConfigurationProperties(prefix = "task.pool") public class TaskThreadPoolConfig {private int corePoolSize;private int maxPoolSize;private int keepAliveSeconds;private int queueCapacity;private int awaitTerminationSeconds;private String threadNamePrefix; }2.3. 開啟異步線程支持
在啟動類上/開啟異步線程支持+開啟配置屬性支持
package com.gblfy;import com.gblfy.config.TaskThreadPoolConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.scheduling.annotation.EnableAsync;@EnableAsync//開啟異步線程支持 @EnableConfigurationProperties({TaskThreadPoolConfig.class})//開啟配置屬性支持 @SpringBootApplication public class AsyncThreadApplication {public static void main(String[] args) {SpringApplication.run(AsyncThreadApplication.class, args);}}2.4. 裝配線程池
package com.gblfy.config;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor;/*** 原生(Spring)異步線程池裝配類* 實現AsyncConfigurer接口,重寫getAsyncExecutor和getAsyncUncaughtExceptionHandler方法,* 這樣使用默認線程池時就會使用自己重寫之后的線程池** @Author gblfy* @Date 2022-04-05 17:26**/ @Configuration public class NativeAsyncScheduledTaskConfig implements AsyncConfigurer {private static final Logger LOGGER = LoggerFactory.getLogger(NativeAsyncScheduledTaskConfig.class);@Autowiredprivate TaskThreadPoolConfig config;@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//最大線程數executor.setMaxPoolSize(config.getMaxPoolSize());//核心線程數executor.setCorePoolSize(config.getCorePoolSize());//任務隊列的大小executor.setQueueCapacity(config.getQueueCapacity());//線程池名的前綴executor.setThreadNamePrefix(config.getThreadNamePrefix());//允許線程的空閑時間30秒executor.setKeepAliveSeconds(config.getKeepAliveSeconds());//設置線程池關閉的時候等待所有任務都完成再繼續銷毀其他的Beanexecutor.setWaitForTasksToCompleteOnShutdown(true);//設置線程池中任務的等待時間,如果超過這個時候還沒有銷毀就強制銷毀,以確保應用最后能夠被關閉,而不是阻塞住executor.setAwaitTerminationSeconds(config.getAwaitTerminationSeconds());/*** 拒絕處理策略* CallerRunsPolicy():交由調用方線程運行,比如 main 線程。* AbortPolicy():直接拋出異常。* DiscardPolicy():直接丟棄。* DiscardOldestPolicy():丟棄隊列中最老的任務。*//*** 特殊說明:* 1. 這里演示環境,拒絕策略咱們采用拋出異常* 2.真實業務場景會把緩存隊列的大小會設置大一些,* 如果,提交的任務數量超過最大線程數量或將任務環緩存到本地、redis、mysql中,保證消息不丟失* 3.如果項目比較大的話,異步通知種類很多的話,建議采用MQ做異步通知方案*/executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//線程初始化executor.initialize();return executor;}/*** 異步任務重異常處理** @return*/@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return (ex, method, params) -> {LOGGER.error(ex.getMessage(), ex);LOGGER.error("excetion method:{}", method.getName());};}// @Override// public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {// return new AsyncUncaughtExceptionHandler() {// @Override// public void handleUncaughtException(Throwable ex, Method method, Object... params) {// LOGGER.error(ex.getMessage(),ex);// LOGGER.error("excetion method:{}",method.getName());// }// };// } }2.5. service邏輯層
package com.gblfy.service;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;/*** 重寫Spring默認線程池測試1** @Author gblfy* @Date 2022-04-05 17:55**/ @Service public class ThreadPoolService3 {private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolService3.class);@Asyncpublic void executeAsync() {System.out.println("executeAsync3");LOGGER.info("當前運行線程名稱:{}", Thread.currentThread().getName());} } package com.gblfy.service;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;/*** 重寫Spring默認線程池測試2** @Author gblfy* @Date 2022-04-05 17:55**/ @Service public class ThreadPoolService4 {private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolService4.class);@Asyncpublic void executeAsync() {System.out.println("executeAsync4");LOGGER.info("當前運行線程名稱:{}", Thread.currentThread().getName());} }2.6. controller控制層
package com.gblfy.controller;import com.gblfy.service.ThreadPoolService3; import com.gblfy.service.ThreadPoolService4; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;/*** 自定義線程池側是** @Author gblfy* @Date 2022-04-05 17:54**/ @RestController public class ThreadPoolController2 {@Autowiredprivate ThreadPoolService3 threadPoolService3;@Autowiredprivate ThreadPoolService4 threadPoolService4;@GetMapping("/threadPoolTest2")public void threadPoolTest2() {threadPoolService3.executeAsync();threadPoolService4.executeAsync();} }2.7. 效果圖
瀏覽器請求:http://localhost:8080/threadPoolTest2
總結
以上是生活随笔為你收集整理的SpringBoot 自定义线程池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端传递多个数组以及其他参数,sprin
- 下一篇: SpringBoot 使用宝兰德中间件替