From fa16b55b6aade8b486a651756d676c327e9faedc Mon Sep 17 00:00:00 2001 From: yennanliu Date: Fri, 22 Dec 2023 17:06:14 +0800 Subject: [PATCH] add taskExecutorConf, add async annotation, add code comment --- .../springWarehouse/WarehouseApplication.java | 2 + .../config/TaskExecutorConfig.java | 80 +++++++++++++++++++ .../controller/DownloadController.java | 7 +- .../impl/DownloadStatusServiceImpl.java | 1 + .../service/impl/ProductTypeServiceImpl.java | 2 + 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 springWarehouse/src/main/java/com/yen/springWarehouse/config/TaskExecutorConfig.java diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/WarehouseApplication.java b/springWarehouse/src/main/java/com/yen/springWarehouse/WarehouseApplication.java index 288ecc161..b3be9852a 100644 --- a/springWarehouse/src/main/java/com/yen/springWarehouse/WarehouseApplication.java +++ b/springWarehouse/src/main/java/com/yen/springWarehouse/WarehouseApplication.java @@ -3,8 +3,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.Async; import org.springframework.transaction.annotation.EnableTransactionManagement; +//@Async // enable async, let Spring auto do op with async @ComponentScan(basePackages = "com.yen.springWarehouse") @org.mybatis.spring.annotation.MapperScan("com.yen.springWarehouse.mapper") @EnableTransactionManagement // TODO : recheck this diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/config/TaskExecutorConfig.java b/springWarehouse/src/main/java/com/yen/springWarehouse/config/TaskExecutorConfig.java new file mode 100644 index 000000000..2639ac8c1 --- /dev/null +++ b/springWarehouse/src/main/java/com/yen/springWarehouse/config/TaskExecutorConfig.java @@ -0,0 +1,80 @@ +package com.yen.springWarehouse.config; + +// https://github.com/timebusker/spring-boot/blob/master/spring-boot-5-Async/src/main/java/cn/timebusker/config/TaskExecutorConfig.java + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@Configuration +@EnableAsync +public class TaskExecutorConfig implements AsyncConfigurer{ + + /** + * Set the ThreadPoolExecutor's core pool size. + */ + private static final int CORE_POOL_SIZE = 5; + + /** + * Set the ThreadPoolExecutor's maximum pool size. + */ + private static final int MAX_POOL_SIZE = 20; + + /** + * Set the capacity for the ThreadPoolExecutor's BlockingQueue. + */ + private static final int QUEUE_CAPACITY = 10; + + /** + * 通过重写getAsyncExecutor方法,制定默认的任务执行由该方法产生 + * + * 配置类实现AsyncConfigurer接口并重写getAsyncExcutor方法,并返回一个ThreadPoolTaskExevutor + * 这样我们就获得了一个基于线程池的TaskExecutor + */ + @Override + public Executor getAsyncExecutor() { + + System.out.println(">>> getAsyncExecutor ..."); + + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(CORE_POOL_SIZE);// 线程池维护线程的最少数量 + taskExecutor.setMaxPoolSize(MAX_POOL_SIZE);// 线程池维护线程的最大数量 + taskExecutor.setQueueCapacity(QUEUE_CAPACITY);// 线程池所使用的缓冲队列 + taskExecutor.initialize(); + + return taskExecutor; + } + + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return null; + } + + /** + * 自定义任务执行器:在定义了多个任务执行器的情况下,可以使用@Async("getMineAsync")来设定 + * + * @return + */ + @Bean + public Executor getMineAsync() { + + System.out.println(">>> getMineAsync ... "); + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(CORE_POOL_SIZE - 4); + executor.setMaxPoolSize(MAX_POOL_SIZE - 10); + executor.setQueueCapacity(QUEUE_CAPACITY - 5); + executor.setThreadNamePrefix("mineAsync-"); + // rejection-policy:当pool已经达到max size的时候,如何处理新任务 + // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + executor.initialize(); + return executor; + } + +} diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/controller/DownloadController.java b/springWarehouse/src/main/java/com/yen/springWarehouse/controller/DownloadController.java index 9e59b6221..ac4fe39e2 100644 --- a/springWarehouse/src/main/java/com/yen/springWarehouse/controller/DownloadController.java +++ b/springWarehouse/src/main/java/com/yen/springWarehouse/controller/DownloadController.java @@ -65,12 +65,17 @@ public String list(Map map, @RequestParam(value="pageNo", requir } @GetMapping("/create_report") - public String createDownload() { + public String createDownload() throws InterruptedException { DateTimeUtils dateTimeUtils = new DateTimeUtils(); String timestamp = dateTimeUtils.getCurrentDateYYYYMMDDHHMMSS(); FileUtil fileUtil = new FileUtil(); +// log.info("--------------------------------------------\n"); +// log.info(">>>>>>>>> SLEEP 10 SECONDS >>>>>>>>>\n"); +// Thread.sleep(10000); +// log.info("--------------------------------------------\n"); + // create report String fileName = timestamp + "_report.json"; Map map = new HashMap<>(); diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/DownloadStatusServiceImpl.java b/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/DownloadStatusServiceImpl.java index b917dd5c1..705b2ac14 100644 --- a/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/DownloadStatusServiceImpl.java +++ b/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/DownloadStatusServiceImpl.java @@ -4,6 +4,7 @@ import com.yen.springWarehouse.bean.DownloadStatus; import com.yen.springWarehouse.mapper.DownloadStatusMapper; import com.yen.springWarehouse.service.DownloadStatusService; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/ProductTypeServiceImpl.java b/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/ProductTypeServiceImpl.java index ae0273bd6..408e2b6d3 100644 --- a/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/ProductTypeServiceImpl.java +++ b/springWarehouse/src/main/java/com/yen/springWarehouse/service/impl/ProductTypeServiceImpl.java @@ -8,6 +8,7 @@ import com.yen.springWarehouse.mapper.ProductTypeMapper; import com.yen.springWarehouse.service.ProductTypeService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,6 +16,7 @@ // -> we don't implement every abstract method in ProductTypeService, but we extend ServiceImpl first // then implement rest of the abstract methods @Service +//@Async("getMineAsync") @Transactional(rollbackFor = Exception.class) public class ProductTypeServiceImpl extends ServiceImpl implements ProductTypeService {