一、使用ExecutorService
1、配置线程池数量
@Configuration public class ThreadPoolConfig { @Bean public ExecutorService getThreadPool(){ return Executors.newFixedThreadPool(8); } }
2、service 使用方式。
@Service public class UserServiceImpl implements IUserService { @Autowired private ExecutorService executorService; @Override public User query() { executorService.execute(new Runnable() { public void run() { System.out.println("Asynchronous task"); } }); User user = new User(); return user; } }
二、通过配置类实现接口AsyncConfigurator,返回一个ThreadPoolTaskExecutor线程池对象。
1、配置异步类
// ThredPoolTaskExcutor的处理流程
// 当池子大小小于corePoolSize,就新建线程,并处理请求
// 当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去workQueue中取任务并处理
// 当workQueue放不下任务时,就新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize,就用RejectedExecutionHandler来做拒绝处理
// 当池子的线程数大于corePoolSize时,多余的线程会等待keepAliveTime长时间,如果无请求可处理就自行销毁
@Configuration @EnableAsync // 启用异步任务 public class AsyncConfiguration implements AsyncConfigurer { // 声明一个线程池(并指定线程池的名字) @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心线程数5:线程池创建时候初始化的线程数 executor.setCorePoolSize(5); //最大线程数5:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程 executor.setMaxPoolSize(5); //缓冲队列500:用来缓冲执行任务的队列 executor.setQueueCapacity(500); //允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁 executor.setKeepAliveSeconds(60); //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池 executor.setThreadNamePrefix("DailyAsync-"); executor.initialize(); return executor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler(); } }
2、实现方法
@Async注解表明该方法是异步方法,如果注解在类上,那表明这个类里面的所有方法都是异步的。
a、无返回值的方法
@Override @Async public User selectById(Long id) { User user = new User(); user.setId(id); System.out.println("线程" + Thread.currentThread().getName() + " 执行异步任务:" + id); return user; }
b、实现由返回值的方法
@Async public Future<Long> subByAsync(Long id ) throws InterruptedException { long start = System.currentTimeMillis(); long sum = 0; Thread.sleep(500); long end = System.currentTimeMillis(); sum = end - start; System.out.println("线程" + Thread.currentThread().getName() + " 执行异步任务:" + id); return new AsyncResult<>(sum); }
单元测试
@Test public void selectByIdTest() { for (int i = 0; i < 10; i++) { iUserService.selectById((long)i); } } 线程DailyAsync-1 执行异步任务:0 线程DailyAsync-2 执行异步任务:1 线程DailyAsync-3 执行异步任务:2 线程DailyAsync-4 执行异步任务:3 线程DailyAsync-5 执行异步任务:4 线程DailyAsync-2 执行异步任务:6 线程DailyAsync-1 执行异步任务:5 线程DailyAsync-5 执行异步任务:9 线程DailyAsync-3 执行异步任务:7 线程DailyAsync-4 执行异步任务:8 @Test public void subByAsyncTest() throws ExecutionException, InterruptedException { for (int i = 0; i < 10; i++) { Future<Long> task = iUserService.subByAsync((long)i); long async = task.get(); System.out.println("异步执行的时间是:" + async + "(毫秒)"); } }
线程DailyAsync-1 执行异步任务:0
异步执行的时间是:500(毫秒)
线程DailyAsync-2 执行异步任务:1
异步执行的时间是:500(毫秒)
线程DailyAsync-3 执行异步任务:2
异步执行的时间是:500(毫秒)
线程DailyAsync-4 执行异步任务:3
异步执行的时间是:500(毫秒)
线程DailyAsync-5 执行异步任务:4
异步执行的时间是:500(毫秒)
线程DailyAsync-1 执行异步任务:5
异步执行的时间是:500(毫秒)
线程DailyAsync-2 执行异步任务:6
异步执行的时间是:500(毫秒)
线程DailyAsync-3 执行异步任务:7
异步执行的时间是:500(毫秒)
线程DailyAsync-4 执行异步任务:8
异步执行的时间是:500(毫秒)
线程DailyAsync-5 执行异步任务:9
异步执行的时间是:500(毫秒)