当初因为零碎越来越简单,导致很多接口速度变慢,这时候就会想到能够利用线程池来解决一些耗时并不影响零碎的操作。
新建Spring Boot我的项目
1. ExecutorConfig.xml
新建线程池配置文件。
@Configuration@EnableAsyncpublic 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(); //配置外围线程数 executor.setCorePoolSize(corePoolSize); //配置最大线程数 executor.setMaxPoolSize(maxPoolSize); //配置队列大小 executor.setQueueCapacity(queueCapacity); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix(namePrefix); // rejection-policy:当pool曾经达到max size的时候,如何解决新工作 // CALLER_RUNS:不在新线程中执行工作,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); return executor; }}
2. application.yml
@Value配置在application.yml,能够参考配置
# 异步线程配置async: executor: thread: # 配置外围线程数 core_pool_size: 10 # 配置最大线程数 max_pool_size: 20 # 配置队列大小 queue_capacity: 99999 # 配置线程池中的线程的名称前缀 name: prefix: async-service-
3. AsyncService.java
创立一个 Service 接口,是异步线程的接口,将办法写入其实现类即可
public interface AsyncService { /** * 执行异步工作的办法,参数本人能够增加 */ void executeAsync();}
4. AsyncServiceImpl.java
实现类,用来写业务逻辑
@Servicepublic class AsyncServiceImpl implements AsyncService { private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class); @Override @Async("asyncServiceExecutor") public void executeAsync() { logger.info("start executeAsync"); System.out.println("异步线程执行开始了"); System.out.println("能够将耗时的操作放到这里执行了"); logger.info("end executeAsync"); }}
++将 Service 层的服务异步化,在executeAsync()办法上减少注解@Async("asyncServiceExecutor"),asyncServiceExecutor办法是后面ExecutorConfig.java中的办法名,表明executeAsync办法进入的线程池是asyncServiceExecutor办法创立的。++
5. AsyncController.java
在控制器外面注入AsyncService,调用其中的办法即可
@Autowiredprivate AsyncService asyncService;@GetMapping("/async")public void async(){ asyncService.executeAsync();}
6. 用Postman进行测试
打印log入下
2021-06-16 22:15:47.655 INFO 10516 --- [async-service-5] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync异步线程执行开始了能够将耗时的操作放到这里执行了2021-06-16 22:15:47.655 INFO 10516 --- [async-service-5] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync2021-06-16 22:15:47.770 INFO 10516 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync异步线程执行开始了能够将耗时的操作放到这里执行了2021-06-16 22:15:47.770 INFO 10516 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync2021-06-16 22:15:47.816 INFO 10516 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync异步线程执行开始了能够将耗时的操作放到这里执行了2021-06-16 22:15:47.816 INFO 10516 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync2021-06-16 22:15:48.833 INFO 10516 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync异步线程执行开始了能够将耗时的操作放到这里执行了2021-06-16 22:15:48.834 INFO 10516 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync2021-06-16 22:15:48.986 INFO 10516 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync异步线程执行开始了能够将耗时的操作放到这里执行了2021-06-16 22:15:48.987 INFO 10516 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync
至此简略的线程池曾经实现了。
5. 将以后线程池的运行状况打印进去
5.1 VisiableThreadPoolTaskExecutor.java
public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { private static final Logger logger = LoggerFactory.getLogger(VisiableThreadPoolTaskExecutor.class); private void showThreadPoolInfo(String prefix) { ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor(); if (null == threadPoolExecutor) { return; } logger.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]", this.getThreadNamePrefix(), prefix, threadPoolExecutor.getTaskCount(), threadPoolExecutor.getCompletedTaskCount(), threadPoolExecutor.getActiveCount(), threadPoolExecutor.getQueue().size()); } @Override public void execute(Runnable task) { showThreadPoolInfo("1. do execute"); super.execute(task); } @Override public void execute(Runnable task, long startTimeout) { showThreadPoolInfo("2. do execute"); super.execute(task, startTimeout); } @Override public Future<?> submit(Runnable task) { showThreadPoolInfo("1. do submit"); return super.submit(task); } @Override public <T> Future<T> submit(Callable<T> task) { showThreadPoolInfo("2. do submit"); return super.submit(task); } @Override public ListenableFuture<?> submitListenable(Runnable task) { showThreadPoolInfo("1. do submitListenable"); return super.submitListenable(task); } @Override public <T> ListenableFuture<T> submitListenable(Callable<T> task) { showThreadPoolInfo("2. do submitListenable"); return super.submitListenable(task); }}
5.2 批改asyncServiceExecutor.java
批改ExecutorConfig.java的asyncServiceExecutor办法,将ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor()改为ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor()
@Bean(name = "asyncServiceExecutor") public Executor asyncServiceExecutor() { logger.info("start asyncServiceExecutor"); //在这里批改 ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor(); //配置外围线程数 executor.setCorePoolSize(corePoolSize); //配置最大线程数 executor.setMaxPoolSize(maxPoolSize); //配置队列大小 executor.setQueueCapacity(queueCapacity); //配置线程池中的线程的名称前缀 executor.setThreadNamePrefix(namePrefix); // rejection-policy:当pool曾经达到max size的时候,如何解决新工作 // CALLER_RUNS:不在新线程中执行工作,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //执行初始化 executor.initialize(); return executor; }
5.3 应用Postman进行测试
2021-06-16 22:23:30.951 INFO 14088 --- [nio-8087-exec-2] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [0], completedTaskCount [0], activeCount [0], queueSize [0]2021-06-16 22:23:30.952 INFO 14088 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync异步线程执行开始了能够将耗时的操作放到这里执行了2021-06-16 22:23:30.953 INFO 14088 --- [async-service-1] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync2021-06-16 22:23:31.351 INFO 14088 --- [nio-8087-exec-3] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [1], completedTaskCount [1], activeCount [0], queueSize [0]2021-06-16 22:23:31.353 INFO 14088 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync异步线程执行开始了能够将耗时的操作放到这里执行了2021-06-16 22:23:31.353 INFO 14088 --- [async-service-2] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync2021-06-16 22:23:31.927 INFO 14088 --- [nio-8087-exec-5] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [2], completedTaskCount [2], activeCount [0], queueSize [0]2021-06-16 22:23:31.929 INFO 14088 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync异步线程执行开始了能够将耗时的操作放到这里执行了2021-06-16 22:23:31.930 INFO 14088 --- [async-service-3] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync2021-06-16 22:23:32.496 INFO 14088 --- [nio-8087-exec-7] u.d.e.e.i.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [3], completedTaskCount [3], activeCount [0], queueSize [0]2021-06-16 22:23:32.498 INFO 14088 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl : start executeAsync异步线程执行开始了能够将耗时的操作放到这里执行了2021-06-16 22:23:32.499 INFO 14088 --- [async-service-4] c.u.d.e.executor.impl.AsyncServiceImpl : end executeAsync
能够看到下面async-service-, 2. do submit,taskCount [3], completedTaskCount [3], activeCount [0], queueSize [0]对于线程的信息都打印进去了。
集体博客地址
http://www.zhouzhaodong.xyz