需求

前两天做项目的时候,想提高一下插入表的性能优化,因为是两张表,先插旧的表,紧接着插新的表,一万多条数据就有点慢了

思路

后面就想到了线程池ThreadPoolExecutor,而用的是Spring Boot项目,可以用Spring提供的对ThreadPoolExecutor封装的线程池ThreadPoolTaskExecutor,直接使用注解启用

实现

image.png

  1. 线程池配置类

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

  1. package com.threadpooltaskexecutor.threadpooltaskexecutordemo.config;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.scheduling.annotation.EnableAsync;
  7. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  8. import java.util.concurrent.Executor;
  9. import java.util.concurrent.ThreadPoolExecutor;
  10. /**
  11. * @version 1.0
  12. * @Description 线程池配置类 异步
  13. * @Date 2021/8/13 11:04
  14. * @Author wangyun
  15. */
  16. @Configuration
  17. @EnableAsync
  18. @Slf4j
  19. public class ExecutorConfig {
  20. /**
  21. * 核心线程数 数量
  22. */
  23. @Value("${async.executor.thread.core_pool_size}")
  24. private int corePoolSize;
  25. /**
  26. * 最大线程数 数量
  27. */
  28. @Value("${async.executor.thread.max_pool_size}")
  29. private int maxPoolSize;
  30. /**
  31. * 等待队列大小
  32. */
  33. @Value("${async.executor.thread.queue_capacity}")
  34. private int queueCapacity;
  35. /**
  36. * 线程池中的线程名称前缀
  37. */
  38. @Value("${async.executor.thread.name.prefix}")
  39. private String namePrefix;
  40. @Bean("asyncServiceExecutor")
  41. public Executor asyncServiceExecutor(){
  42. log.info("start asyncServiceExecutor");
  43. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  44. //配置核心线程数
  45. executor.setCorePoolSize(corePoolSize);
  46. //配置最大线程数
  47. executor.setMaxPoolSize(maxPoolSize);
  48. //配置队列大小
  49. executor.setQueueCapacity(queueCapacity);
  50. //配置线程池中的线程的名称前缀
  51. executor.setThreadNamePrefix(namePrefix);
  52. // rejection-policy:当pool已经达到max size的时候,如何处理新任务
  53. // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
  54. executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  55. //执行初始化
  56. executor.initialize();
  57. return executor;
  58. }
  59. }
  1. 创建一个Service接口,是异步线程的接口 ```java package com.threadpooltaskexecutor.threadpooltaskexecutordemo.service;

/**

  • @version 1.0
  • @Description
  • @Date 2021/8/13 11:38
  • @Author wangyun */

public interface AsyncService {

  1. /**
  2. * 执行异步任务
  3. * 可以根据需求,自己加参数拟定,我这里就做个测试演示
  4. *
  5. */
  6. void executeAsync() throws InterruptedException;

}

  1. 3. service 实现
  2. ```java
  3. package com.threadpooltaskexecutor.threadpooltaskexecutordemo.service.impl;
  4. import com.threadpooltaskexecutor.threadpooltaskexecutordemo.service.AsyncService;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.scheduling.annotation.Async;
  7. import org.springframework.stereotype.Service;
  8. import java.util.concurrent.TimeUnit;
  9. /**
  10. * @version 1.0
  11. * @Description
  12. * @Date 2021/8/13 11:39
  13. * @Author wangyun
  14. */
  15. @Service
  16. @Slf4j
  17. public class AsyncServiceImpl implements AsyncService {
  18. /**
  19. * 执行异步任务
  20. * 可以根据需求,自己加参数拟定,我这里就做个测试演示
  21. */
  22. @Override
  23. @Async("asyncServiceExecutor") //这里是异步线程池的名字
  24. public void executeAsync() throws InterruptedException {
  25. log.info("In AsyncServiceImpl Class, begin execute executeAsync");
  26. log.info("异步线程要做的事情");
  27. TimeUnit.SECONDS.sleep(5); //模拟要执行耗时的操作
  28. log.info("可以在这里执行批量插入等耗时的事情");
  29. log.info("In AsyncServiceImpl Class, end execute executeAsync");
  30. }
  31. }
  1. yml
    1. async:
    2. executor:
    3. thread:
    4. core_pool_size: 5
    5. max_pool_size: 5
    6. queue_capacity: 99999
    7. name:
    8. prefix: async-service-

代码

注意:下载后,请将.pdf后缀去除

threadpooltaskexecutor-demo.rar.pdf

参考链接

点我