传统的请求,都是单线程的!但是线程名不一样!很多时候就会造成堵塞!
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);
@Override
public void executeAsync() {
logger.info("Start executeAsync");
try {
Thread.sleep(10000);
logger.info("当前线程名:"+Thread.currentThread().getName());
} catch (Exception e) {
logger.error("executeAsync exception");
}
logger.info("end executeAsync");
}
}
下面代码包含了线程池的4种 拒绝策略 RejectedExecutor 下面代码注释有说明
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @author : zanglikun
* @date : 2021/12/30 9:39
* @Version: 1.0
* @Desc : 线程池的配置
*/
@Configuration
@EnableAsync
public class ExecutorConfig {
private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
// 定义一个线程池 方法名很重要!其他方法使用线程池必须指定此方法!
@Bean
public Executor asyncServiceExecutor(){
logger.info("Start AsyncServiceExecutor");
ThreadPoolTaskExecutor threadPoolExecutor = new ThreadPoolTaskExecutor();
// 配置设定核心线程数: 最小存在的线程数,如果当前线程小于队列数,依旧会创建线程!使得总线程数 >= 核心线程数
threadPoolExecutor.setCorePoolSize(5);
// 配置最大线程数
threadPoolExecutor.setMaxPoolSize(5);
// 配置非核心线程空闲线程存活时间 单位秒 默认是60秒
threadPoolExecutor.setKeepAliveSeconds(60);
// 允许运行线程数量为 0 这个一般不设置
//threadPoolExecutor.setAllowCoreThreadTimeOut(true);
// 配置待执行任务队列大小 默认是(Interger.MaxValue)
threadPoolExecutor.setQueueCapacity(10);
// 配置线程池中线程的前缀名
threadPoolExecutor.setThreadNamePrefix("Async-service-");
// 配置阻塞队列满后执行拒绝策略。
/*
AbortPolicy 这是默认策略。队列满了,是直接抛出 RejectedExecutionException 异常。
CallerRunsPolicy 是阻塞新任务进入队列。如果当线程池的线程有空余,才回去读取队列任务执行,才会将阻塞任务加入队列。
DiscardOldestPolicy 是丢弃队列中靠最前的任务。 如果队列有A、B、C 的3个阻塞,此时没有新的线程空闲,突然来了D线程,A线程就会被D代替。此时队列的排序是 B、C、D
DiscardPolicy 是队列满了,直接丢弃新的任务。
*/
threadPoolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
threadPoolExecutor.initialize();
logger.info("End AsyncServiceRxecutor");
return threadPoolExecutor;
}
}
接下来 在ServiceImpl 的具体方法加入 注解@Async(”线程池的方法“)
@Override
@Async("asyncServiceExecutor")
//@Async("这里填写的是你线程池的方法名,此处如果不写,会使用Spring默认的线程池")
public void executeAsync() {
logger.info("Start executeAsync");
try {
Thread.sleep(10000);
logger.info("当前线程名:"+Thread.currentThread().getName());
} catch (Exception e) {
logger.error("executeAsync exception");
}
logger.info("end executeAsync");
}
结果是:
2021-12-30 18:47:22.597 INFO 15728 --- [Async-service-1] c.x.z.s.serviceImpl.AsyncServiceImpl : Start executeAsync
2021-12-30 18:47:22.841 INFO 15728 --- [Async-service-2] c.x.z.s.serviceImpl.AsyncServiceImpl : Start executeAsync
2021-12-30 18:47:32.598 INFO 15728 --- [Async-service-1] c.x.z.s.serviceImpl.AsyncServiceImpl : 当前线程名:Async-service-1
2021-12-30 18:47:32.598 INFO 15728 --- [Async-service-1] c.x.z.s.serviceImpl.AsyncServiceImpl : end executeAsync
2021-12-30 18:47:32.842 INFO 15728 --- [Async-service-2] c.x.z.s.serviceImpl.AsyncServiceImpl : 当前线程名:Async-service-2
2021-12-30 18:47:32.842 INFO 15728 --- [Async-service-2] c.x.z.s.serviceImpl.AsyncServiceImpl : end executeAsync
Async-service-1 执行的时候 与 Async-service-2 执行时并行处理,不冲突、不阻塞!这就是线程池的异步执行!
完结!
特殊说明:以上文章,均是我实际操作,写出来的笔记资料,不会盗用别人文章!烦请各位,请勿直接盗用!转载记得标注来源!