首先创建一个配置类
@Configuration和@EnableAsync这两个注解,表示这是个配置类,并且是线程池的配置类
@Configuration
@EnableAsync
public class ExecutorConfig {
private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
@Bean
public Executor asyncServiceExecutor() {
logger.info("start asyncServiceExecutor");
//ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//使用继承类,查看线程状态
ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(5);
//配置最大线程数
executor.setMaxPoolSize(5);
//配置队列大小
executor.setQueueCapacity(99999);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("async-service-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
创建一个service类
public interface AsyncService {
/**
* 执行异步任务
*/
void executeAsync();
}
创建service的实现类
asyncServiceExecutor是前面ExecutorConfig.java中的方法名,表明executeAsync方法进入的线程池是asyncServiceExecutor方法创建的
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);
@Override
@Async("asyncServiceExecutor")//asyncServiceExecutor是前面ExecutorConfig.java中的方法名,表明executeAsync方法进入的线程池是asyncServiceExecutor方法创建的
public void executeAsync() {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
logger.info("异步开始---"+df.format(new Date()));
try{
Thread.sleep(2000);
}catch(Exception e){
e.printStackTrace();
}
SimpleDateFormat dfa = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
logger.info("异步结束---"+dfa.format(new Date()));
}
}
创建cntorller
@RestController
public class AsyncController {
private static final Logger logger = LoggerFactory.getLogger(AsyncController.class);
@Autowired
private AsyncService asyncServ1ice;
@RequestMapping("hello")
public String hello(){
logger.info("请求开始");
asyncServ1ice.executeAsync();
logger.info("请求返回");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
return df.format(new Date());
}
}
下面我们创建一个类来实现ThreadPoolTaskExecutor,用于查看线程状态
public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
private static final Logger logger = LoggerFactory.getLogger(VisiableThreadPoolTaskExecutor.class);
private void showThreadPoolInfo(String prefix){
ThreadPoolExecutor threadPoolExecutor = getThreadPoolExecutor();
if(null==threadPoolExecutor){
return;
}
logger.info("{}, {},任务总数:taskCount [{}], 已完成数:completedTaskCount [{}], 活跃线程数:activeCount [{}], 队列大小:queueSize [{}]",
this.getThreadNamePrefix(),
prefix,
threadPoolExecutor.getTaskCount(),
threadPoolExecutor.getCompletedTaskCount(),
threadPoolExecutor.getActiveCount(),
threadPoolExecutor.getQueue().size());
}
@Override
public void execute(Runnable task) {
showThreadPoolInfo("1. do execute");
super.execute(task);
}
@Override
public void execute(Runnable task, long startTimeout) {
showThreadPoolInfo("2. do execute");
super.execute(task, startTimeout);
}
@Override
public Future<?> submit(Runnable task) {
showThreadPoolInfo("1. do submit");
return super.submit(task);
}
@Override
public <T> Future<T> submit(Callable<T> task) {
showThreadPoolInfo("2. do submit");
return super.submit(task);
}
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
showThreadPoolInfo("1. do submitListenable");
return super.submitListenable(task);
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
showThreadPoolInfo("2. do submitListenable");
return super.submitListenable(task);
}
}
看看打印出来的东西
2019-10-03 20:04:37.837 INFO 4208 --- [nio-8080-exec-9] c.threadpool.contorller.AsyncController : 请求开始
2019-10-03 20:04:37.838 INFO 4208 --- [nio-8080-exec-9] c.t.c.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,任务总数:taskCount [13], 已完成数:completedTaskCount [13], 活跃线程数:activeCount [0], 队列大小:queueSize [0]
2019-10-03 20:04:37.838 INFO 4208 --- [nio-8080-exec-9] c.threadpool.contorller.AsyncController : 请求返回
2019-10-03 20:04:37.838 INFO 4208 --- [async-service-4] c.t.service.impl.AsyncServiceImpl : 异步开始---2019-10-03 20:04:37
2019-10-03 20:04:39.839 INFO 4208 --- [async-service-4] c.t.service.impl.AsyncServiceImpl : 异步结束---2019-10-03 20:04:39
上面可以看出,contorlle里面调用的service方法是异步执行的,而且线程的状态也在监控中可以查看,这个对于小项目很实用,因为你可能会因为要异步执行去考虑消息队列,这样有点麻烦,用线程异步执行就比较方便,当然用什么技术还是要结合自己的实际业务,技术没有最好的,只有最合适的