当前位置:   article > 正文

Springboot线程池并发处理数据优化_springboot async优化

springboot async优化

第一步:首先配置线程基本参数,可以放在application.propertes文件种也可以放在自己新建的config/文件目录下,注意:但是需要使用@PropertySource把配置文件进行加载。

  1. # 异步线程配置
  2. # 配置核心线程数
  3. async.executor.thread.core_pool_size = 8
  4. # 配置最大线程数
  5. async.executor.thread.max_pool_size = 20
  6. # 配置队列大小
  7. async.executor.thread.queue_capacity = 99999
  8. # 配置线程池中的线程的名称前缀
  9. async.executor.thread.name.prefix = async-service-

第二步:让Spring Boot加载,用来定义如何创建一个ThreadPoolTaskExecutor,要使用@Configuration和@EnableAsync这两个注解,表示这是个配置类,并且是线程池的配置类

  1. @Slf4j
  2. @EnableAsync
  3. @Configuration
  4. public class RCExecutorConfig {
  5. @Value("${async.executor.thread.core_pool_size}")
  6. private int corePoolSize;
  7. @Value("${async.executor.thread.max_pool_size}")
  8. private int maxPoolSize;
  9. @Value("${async.executor.thread.queue_capacity}")
  10. private int queueCapacity;
  11. @Value("${async.executor.thread.name.prefix}")
  12. private String namePrefix;
  13. @Bean(name = "asyncServiceExecutor")
  14. public Executor asyncServiceExecutor() {
  15. log.info("start asyncServiceExecutor");
  16. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  17. //ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
  18. //配置核心线程数
  19. executor.setCorePoolSize(corePoolSize);
  20. //配置最大线程数
  21. executor.setMaxPoolSize(maxPoolSize);
  22. //配置队列大小
  23. executor.setQueueCapacity(queueCapacity);
  24. //配置线程池中的线程的名称前缀
  25. executor.setThreadNamePrefix(namePrefix);
  26. // rejection-policy:当pool已经达到max size的时候,如何处理新任务
  27. // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
  28. executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  29. //执行初始化
  30. executor.initialize();
  31. return executor;
  32. }
  33. }

第三步:创建一个service接口,是异步线程的接口,便于测试

  1. public interface AsyncService {
  2. /**
  3. * 执行异步任务
  4. * 可以根据需求,自己加参数拟定
  5. */
  6. void executeAsync();
  7. }

第四步:编写现实类,将Service层的服务异步化,在executeAsync()方法上增加注解@Async("asyncServiceExecutor"),asyncServiceExecutor方法是前面RCExecutorConfig.java中的方法名,表明executeAsync方法进入的线程池是asyncServiceExecutor方法创建的。测试方面这里我加入了一个定时任务,使用的是corn表达式。(不懂得同学可以网上了解一下)

  1. @Slf4j
  2. @Service
  3. public class AsyncServiceImpl implements AsyncService {
  4. @Override
  5. @Scheduled(cron = " */1 * * * * ? ")
  6. @Async("asyncServiceExecutor")
  7. public void executeAsync() {
  8. log.info("start executeAsync");
  9. System.out.println("异步线程执行批量插入等耗时任务");
  10. log.info("end executeAsync");
  11. }
  12. }

第五步:测试结果如下:

  1. 10:32:15.004 [async-service-1] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  2. 异步线程执行批量插入等耗时任务
  3. 10:32:15.004 [async-service-1] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  4. 10:32:16.003 [async-service-2] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  5. 异步线程执行批量插入等耗时任务
  6. 10:32:16.004 [async-service-2] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  7. 10:32:17.001 [async-service-3] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  8. 异步线程执行批量插入等耗时任务
  9. 10:32:17.001 [async-service-3] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  10. 10:32:18.002 [async-service-4] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  11. 异步线程执行批量插入等耗时任务
  12. 10:32:18.003 [async-service-4] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  13. 10:32:19.002 [async-service-5] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  14. 异步线程执行批量插入等耗时任务
  15. 10:32:19.003 [async-service-5] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  16. 10:32:20.001 [async-service-6] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  17. 异步线程执行批量插入等耗时任务
  18. 10:32:20.002 [async-service-6] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  19. 10:32:21.002 [async-service-7] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  20. 异步线程执行批量插入等耗时任务
  21. 10:32:21.002 [async-service-7] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  22. 10:32:22.004 [async-service-8] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  23. 异步线程执行批量插入等耗时任务
  24. 10:32:22.005 [async-service-8] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  25. 10:32:23.001 [async-service-1] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  26. 异步线程执行批量插入等耗时任务
  27. 10:32:23.003 [async-service-1] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  28. 10:32:24.003 [async-service-2] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  29. 异步线程执行批量插入等耗时任务
  30. 10:32:24.003 [async-service-2] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  31. 10:32:25.001 [async-service-3] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  32. 异步线程执行批量插入等耗时任务
  33. 10:32:25.001 [async-service-3] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  34. 10:32:26.002 [async-service-4] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  35. 异步线程执行批量插入等耗时任务
  36. 10:32:26.002 [async-service-4] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  37. 10:32:27.002 [async-service-5] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  38. 异步线程执行批量插入等耗时任务
  39. 10:32:27.003 [async-service-5] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  40. 10:32:28.001 [async-service-6] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  41. 异步线程执行批量插入等耗时任务
  42. 10:32:28.001 [async-service-6] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  43. 10:32:29.001 [async-service-7] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  44. 异步线程执行批量插入等耗时任务
  45. 10:32:29.002 [async-service-7] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  46. 10:32:30.001 [async-service-8] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  47. 异步线程执行批量插入等耗时任务
  48. 10:32:30.001 [async-service-8] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  49. 10:32:31.001 [async-service-1] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  50. 异步线程执行批量插入等耗时任务
  51. 10:32:31.001 [async-service-1] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync

还没完:

通过以上日志可以发现,[async-service-]是有多个线程的,显然已经在我们配置的线程池中执行了,表明每次请求都快速响应了,而耗时的操作都留给线程池中的线程去异步执行;

还有另一个问提就是,虽然已经用上了线程池,但是依然不清楚线程池当时的情况,有多少线程在执行,多少在队列中等待呢?于是这里我创建了一个ThreadPoolTaskExecutor的子类,可以把每次提交线程的时候都会将当前线程池的运行状况打印出来

  1. import lombok.extern.slf4j.Slf4j;
  2. @Slf4j
  3. public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
  4. /**
  5. *
  6. */
  7. private static final long serialVersionUID = -3518460523928455463L;
  8. private void showThreadPoolInfo(String prefix) {
  9. ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor();
  10. if (null == threadPoolExecutor) {
  11. return;
  12. }
  13. log.info("{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize [{}]",
  14. this.getThreadNamePrefix(),
  15. prefix,
  16. threadPoolExecutor.getTaskCount(),
  17. threadPoolExecutor.getCompletedTaskCount(),
  18. threadPoolExecutor.getActiveCount(),
  19. threadPoolExecutor.getQueue().size());
  20. }
  21. @Override
  22. public void execute(Runnable task) {
  23. showThreadPoolInfo("1. do execute");
  24. super.execute(task);
  25. }
  26. @Override
  27. public void execute(Runnable task, long startTimeout) {
  28. showThreadPoolInfo("2. do execute");
  29. super.execute(task, startTimeout);
  30. }
  31. @Override
  32. public Future<?> submit(Runnable task) {
  33. showThreadPoolInfo("1. do submit");
  34. return super.submit(task);
  35. }
  36. @Override
  37. public <T> Future<T> submit(Callable<T> task) {
  38. showThreadPoolInfo("2. do submit");
  39. return super.submit(task);
  40. }
  41. @Override
  42. public ListenableFuture<?> submitListenable(Runnable task) {
  43. showThreadPoolInfo("1. do submitListenable");
  44. return super.submitListenable(task);
  45. }
  46. @Override
  47. public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
  48. showThreadPoolInfo("2. do submitListenable");
  49. return super.submitListenable(task);
  50. }
  51. }

其次:修改RCExecutorConfig.java的asyncServiceExecutor方法,将ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor()改为ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor()

  1. @Bean(name = "asyncServiceExecutor")
  2. public Executor asyncServiceExecutor() {
  3. log.info("start asyncServiceExecutor");
  4. //ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  5. ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
  6. //配置核心线程数
  7. executor.setCorePoolSize(corePoolSize);
  8. //配置最大线程数
  9. executor.setMaxPoolSize(maxPoolSize);
  10. //配置队列大小
  11. executor.setQueueCapacity(queueCapacity);
  12. //配置线程池中的线程的名称前缀
  13. executor.setThreadNamePrefix(namePrefix);
  14. // rejection-policy:当pool已经达到max size的时候,如何处理新任务
  15. // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
  16. executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  17. //执行初始化
  18. executor.initialize();
  19. return executor;
  20. }

测试结果如下:

  1. 异步线程执行批量插入等耗时任务
  2. 10:41:35.003 [async-service-5] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  3. 10:41:36.001 [sheduled-pool-1-thread-1] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [5], completedTaskCount [5], activeCount [0], queueSize [0]
  4. 10:41:36.001 [async-service-6] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  5. 异步线程执行批量插入等耗时任务
  6. 10:41:36.002 [async-service-6] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  7. 10:41:37.001 [sheduled-pool-1-thread-7] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [6], completedTaskCount [6], activeCount [0], queueSize [0]
  8. 10:41:37.001 [async-service-7] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  9. 异步线程执行批量插入等耗时任务
  10. 10:41:37.002 [async-service-7] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  11. 10:41:38.002 [sheduled-pool-1-thread-7] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [7], completedTaskCount [7], activeCount [0], queueSize [0]
  12. 10:41:38.002 [async-service-8] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  13. 异步线程执行批量插入等耗时任务
  14. 10:41:38.002 [async-service-8] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  15. 10:41:39.001 [sheduled-pool-1-thread-7] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [8], completedTaskCount [8], activeCount [0], queueSize [0]
  16. 10:41:39.001 [async-service-1] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  17. 异步线程执行批量插入等耗时任务
  18. 10:41:39.002 [async-service-1] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  19. 10:41:40.003 [sheduled-pool-1-thread-7] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [9], completedTaskCount [9], activeCount [0], queueSize [0]
  20. 10:41:40.003 [async-service-2] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  21. 异步线程执行批量插入等耗时任务
  22. 10:41:40.003 [async-service-2] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  23. 10:41:41.001 [sheduled-pool-1-thread-7] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [10], completedTaskCount [10], activeCount [0], queueSize [0]
  24. 10:41:41.001 [async-service-3] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  25. 异步线程执行批量插入等耗时任务
  26. 10:41:41.001 [async-service-3] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  27. 10:41:42.000 [sheduled-pool-1-thread-7] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [11], completedTaskCount [11], activeCount [0], queueSize [0]
  28. 10:41:42.000 [async-service-4] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  29. 异步线程执行批量插入等耗时任务
  30. 10:41:42.000 [async-service-4] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  31. 10:41:43.001 [sheduled-pool-1-thread-7] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [12], completedTaskCount [12], activeCount [0], queueSize [0]
  32. 10:41:43.002 [async-service-5] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  33. 异步线程执行批量插入等耗时任务
  34. 10:41:43.003 [async-service-5] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  35. 10:41:44.001 [sheduled-pool-1-thread-7] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [13], completedTaskCount [13], activeCount [0], queueSize [0]
  36. 10:41:44.001 [async-service-6] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync
  37. 异步线程执行批量插入等耗时任务
  38. 10:41:44.001 [async-service-6] INFO c.a.a.service.impl.AsyncServiceImpl - end executeAsync
  39. 10:41:45.000 [sheduled-pool-1-thread-7] INFO c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [14], completedTaskCount [14], activeCount [0], queueSize [0]
  40. 10:41:45.001 [async-service-7] INFO c.a.a.service.impl.AsyncServiceImpl - start executeAsync


解释:这里意思提交了14个任务,处理了14个任务,对列中还剩0个任务

10:41:45.000 [sheduled-pool-1-thread-7] INFO  c.a.a.e.t.VisiableThreadPoolTaskExecutor - async-service-, 2. do submit,taskCount [14], completedTaskCount [14], activeCount [0], queueSize [0]

到此为止就OK了!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/52461
推荐阅读
相关标签
  

闽ICP备14008679号