文章目录
1. 简介
异步指的是每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
2. SpringBoot异步任务实现
2.1 实现一个简单的异步任务
步骤如下:
2.1.1 添加@EnableAsync注解,开启异步任务功能
@EnableAsync@SpringBootApplicationpublicclassUtilsApplication{publicstaticvoidmain(String[] args){SpringApplication.run(UtilsApplication.class, args);}}
2.1.2 定义异步任务
publicinterfaceAsyncService{Future<String>doTask1()throwsException;Future<String>doTask2()throwsException;Future<String>doTask3()throwsException;}
@ServicepublicclassAsyncServiceImplimplementsAsyncService{publicstaticRandom random=newRandom();@Async@OverridepublicFuture<String>doTask1()throwsException{System.out.println("开始做任务一");long start=System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end=System.currentTimeMillis();System.out.println("完成任务一,耗时:"+(end- start)+"毫秒");returnnewAsyncResult<>("任务一完成");}@Async@OverridepublicFuture<String>doTask2()throwsException{System.out.println("开始做任务二");long start=System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end=System.currentTimeMillis();System.out.println("完成任务二,耗时:"+(end- start)+"毫秒");returnnewAsyncResult<>("任务二完成");}@Async@OverridepublicFuture<String>doTask3()throwsException{System.out.println("开始做任务三");long start=System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long end=System.currentTimeMillis();System.out.println("完成任务三,耗时:"+(end- start)+"毫秒");returnnewAsyncResult<>("任务三完成");}}
2.1.3 定义接口
@RestControllerpublicclassAsyncController{@AutowiredAsyncService asyncService;@RequestMapping("/async")publicStringgetEntityById()throwsException{long start=System.currentTimeMillis();Future<String> task1= asyncService.doTask1();Future<String> task2= asyncService.doTask2();Future<String> task3= asyncService.doTask3();while(true){if(task1.isDone()&& task2.isDone()&& task3.isDone()){// 三个任务都调用完成,退出循环等待break;}Thread.sleep(1000);}long end=System.currentTimeMillis();return"任务全部完成,总耗时:"+(end- start)+"毫秒";}}
2.1.4 结果
{"code":200,"message":"成功","data":"任务全部完成,总耗时:10006毫秒"}
2.2 使用自定义的线程池配置
@EnableAsync中的注释:
*Bydefault,Spring will be searchingfor an associated thread pool definition:* either a unique{@linkorg.springframework.core.task.TaskExecutor} bean in the context,* or an{@linkjava.util.concurrent.Executor} bean named"taskExecutor"otherwise. If* neither of the two is resolvable, a{@linkorg.springframework.core.task.SimpleAsyncTaskExecutor}* will be usedtoprocess async methodinvocations. Besides, annotated methods having a*{@codevoid}return type cannot transmit any exception backtothecaller. Bydefault,* such uncaught exceptions are only logged.
2.2.1 实现AsyncConfigurer接口
@Slf4j@ConfigurationpublicclassAsyncConfigimplementsAsyncConfigurer{@OverridepublicExecutorgetAsyncExecutor(){ThreadPoolTaskExecutor executor=newThreadPoolTaskExecutor();
executor.setCorePoolSize(7);
executor.setMaxPoolSize(42);
executor.setQueueCapacity(11);
executor.setThreadNamePrefix("MyExecutor-");
executor.initialize();return executor;}/**
* 异步任务中异常处理
*/@OverridepublicAsyncUncaughtExceptionHandlergetAsyncUncaughtExceptionHandler(){returnnewAsyncUncaughtExceptionHandler(){@OverridepublicvoidhandleUncaughtException(Throwable ex,Method method,Object... params){
log.error("=========================="+ex.getMessage()+"=======================", ex);
log.error("exception method:"+method.getName());}};}}
2.2.2 在AsyncServiceImpl中添加代码
System.out.println("当前线程:"+Thread.currentThread().getName());
2.2.3 结果
当前线程:MyExecutor-3 执行任务3
当前线程:MyExecutor-1 执行任务1
当前线程:MyExecutor-2 执行任务2
完成任务二,耗时:6734毫秒
完成任务一,耗时:7514毫秒
完成任务三,耗时:9308毫秒
{"code":200,"message":"成功","data":"任务全部完成,总耗时:10011毫秒"}