SpringBoot_Thread


SpringBoot_Thread

第一步

  • 定义配置文件
spring:
  task:
    execution:
      pool:
        core-size: 10
        max-size: 20
        queue-capacity: 40
        keep-alive: 60
      thread-name-prefix: thread-

第二步

  • 定义ThreadConfig 的配置
@Configuration
@EnableAsync
public class ThreadConfig implements AsyncConfigurer {

    @Value("${spring.task.execution.pool.core-size}")
    private Integer coreSize;

    @Value("${spring.task.execution.pool.max-size}")
    private Integer maxSize;

    @Value("${spring.task.execution.pool.queue-capacity}")
    private Integer queueCapacity;

    @Value("${spring.task.execution.pool.keep-alive}")
    private Integer keepAlive;

    @Value("${spring.task.execution.thread-name-prefix}")
    private String threadNamePrefix;

    /**
     * ThreadPoolTaskExcutor 运行原理
     * 当线程池的线程数小于 corePoolSize,则新建线程入池处理请求
     * 当线程池的线程数等于 corePoolSize,则将任务放入 Queue 中,线程池中的空闲线程会从 Queue 中获取任务并处理
     * 当Queue中的任务数超过 queueCapacity,则新建线程入池处理请求,但如果线程池线程数达到 maxPoolSize,将会通过 RejectedExecutionHandler 做拒绝处理
     * 当线程池的线程数大于 corePoolSize 时,空闲线程会等待 keepAliveTime 长时间,如果无请求可处理就自行销毁
     */

    @Bean("getAsyncExecutor")
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        /**
         * 核心线程数:线程池创建时候初始化的线程数
         */
        executor.setCorePoolSize(coreSize);

        /**
         * 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
         */
        executor.setMaxPoolSize(maxSize);

        /**
         * 缓冲队列:用来缓冲执行任务的队列
         */
        executor.setQueueCapacity(queueCapacity);

        /**
         * 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁
         */
        executor.setKeepAliveSeconds(keepAlive);

        /**
         * 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
         */
        executor.setThreadNamePrefix(threadNamePrefix);

        /**
         * 缓冲队列满了之后的拒绝策略:在新线程中执行任务,而是有调用者所在的线程来执行
         */
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();

        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }

第三步

  • 定义IThreadService接口
public interface IThreadService {
    void getData();
    void sysData(int i);
}

第四步

  • 定义 ThreadServiceImpl 实现类
/**
 * 注意这两个方法在实现山的异同
 */
@Service
public class ThreadServiceImpl implements IThreadService {
    @Resource
    private Executor executor;

    @Async("getAsyncExecutor")
    @Override
    public void getData() {
        CountDownLatch mainMonitor = new CountDownLatch(1);
        CountDownLatch childMonitor = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            int j = i;
            executor.execute(() -> {
                try {
                    mainMonitor.await();
                    System.out.println("第" + j + "完成任务" + Thread.currentThread().getName());
                    childMonitor.countDown();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        try {
            childMonitor.await();
            mainMonitor.countDown();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("任务释放" + Thread.currentThread().getName());
    }

    @Async("getAsyncExecutor")
    @Override
    public void sysData(int i) {
        System.out.println("线程" + Thread.currentThread().getName() + " 执行异步任务:" + i);
    }
}

第五步

  • Controller层使用
/**
 * 注意这两个方法在使用上的异同
 */
@Controller
public class ThreadController {
    @Resource
    private IThreadService threadService;

    @PostMapping("/getData")
    @ResponseBody
    public boolean getData() {
        threadService.getData();
        return true;
    }

    @PostMapping("/sysData")
    @ResponseBody
    public boolean sysData() {
        for (int i = 0; i < 10; i++) {
            threadService.sysData(i);
        }
        return true;
    }

文章作者: L Q
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 L Q !
  目录