定义线程池
第一步,先定义一个线程池,比如:
@Configuration
public class PoolConfig {
@Bean("testExecutor")
public Executor testExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("testExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
上面我们通过使用ThreadPoolTaskExecutor创建了一个线程池,同时设置了以下这些参数:
- 核心线程数10:线程池创建时候初始化的线程数
- 最大线程数20:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
- 缓冲队列200:用来缓冲执行任务的队列
- 允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
- 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
- 线程池对拒绝任务的处理策略:这里采用了CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
定义异步任务,指定任务使用的线程池
在定义了线程池之后,我们如何让异步调用的任务使用这个线程池中的资源来运行呢?方法非常简单,我们只需要在@Async注解中指定线程池名即可,比如:
@Service
public class TestService {
public static Random random = new Random();
@Async("testExecutor") //-使用此注解的方法就是一个异步执行的任务;指定了要使用的线程池
public void one() throws Exception {
log.info("第一个");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成一,耗时:" + (end - start) + "毫秒");
}
}
调用异步任务
@RestController
public class TestController {
@GetMapping("/{id}/nodes")
public Object one() {
//调用一个异步任务
one();
return "ok"
}
}
访问这个接口的效果是:接口立马响应数据给前端;同时 异步执行 one();