线程池的执行流程
任务被提交到线程池,会先判断当前线程数量是否小于corePoolSize(线程池核心线程数量),如果小于则创建线程来执行提交的任务,否则将任务放入workQueue(线程堵塞队列)缓存队列,如果workQueue缓存队列满了,则判断当前线程数量是否小于maximumPoolSize(线程池最大线程数量),如果小于则创建线程执行任务,否则就会调用handler(拒绝策略),以表示线程池拒绝接收任务。
使用线程池的准备工作
(1)在config包里配置线程池的配置类
package com.saodai.saodaimall.order.config; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 线程池配置类 **/ @EnableConfigurationProperties(ThreadPoolConfigProperties.class) @Configuration public class MyThreadConfig { @Bean public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) { return new ThreadPoolExecutor( //线程池核心线程数量 pool.getCoreSize(), //线程池最大线程数量 pool.getMaxSize(), //线程池(最大线程数量-核心线程数量)的存活时间 pool.getKeepAliveTime(), //存活时间单位 TimeUnit.SECONDS, //线程堵塞队列 new LinkedBlockingDeque<>(100000), //默认线程工厂 Executors.defaultThreadFactory(), //拒绝策略 new ThreadPoolExecutor.AbortPolicy() ); } }
package com.saodai.saodaimall.order.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; /** *线程池核心配置(方便在application.properties中进行配置) **/ @ConfigurationProperties(prefix = "saodaimall.thread") @Data public class ThreadPoolConfigProperties { private Integer coreSize; //线程池核心线程数量 private Integer maxSize; //线程池最大线程数量 private Integer keepAliveTime; //线程池(最大线程数量-核心线程数量)的存活时间 }
(2)在application.xml配置文件中配置线程池核心的配置项
# 线程池核心线程数量 saodaimall.thread.coreSize=20 #线程池最大线程数量 saodaimall.thread.maxSize=200 #线程池(最大线程数量-核心线程数量)的存活时间 saodaimall.thread.keepAliveTime=10
本商城项目哪里用到了线程池
订单服务
在订单服务的确认订单业务的第二步就使用了线程池来实现异步任务
常用线程池的操作
(1)线程池来实现异步任务runAsync+阻塞异步线程(记得都要加上阻塞异步线程)
@Autowired private ThreadPoolExecutor threadPoolExecutor; //线程池 CompletableFuture<Void> A = CompletableFuture.runAsync(() -> { //异步任务A }, threadPoolExecutor); CompletableFuture<Void> B = CompletableFuture.runAsync(() -> { //异步任务B }, threadPoolExecutor);
(2)线程池异步任务runAsync+thenRunAsync+阻塞异步线程
这个跟上面的区别就是异步任务A执行后才会执行异步任务B,上面的异步任务A和异步任务B是同时执行的
CompletableFuture<Void> A = CompletableFuture.runAsync(() -> { //异步任务A }, threadPoolExecutor).thenRunAsync(() -> { //异步任务B },threadPoolExecutor);
(3)阻塞异步线程
1. //阻塞异步线程,只有两个异步都完成了才可以进行下一步 2. CompletableFuture.allOf(A,B).get(); //A,B是指上面的上个异步任务