SpringBoot集成篇(二) 异步调用Async
什么是异步调用?
异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行。
如何实现异步调用?
多线程,这是很多人第一眼想到的关键词,没错,多线程就是一种实现异步调用的方式。
在非spring目项目中我们要实现异步调用的就是使用多线程方式,可以自己实现Runable接口或者集成Thread类,或者使用jdk1.5以上提供了的Executors线程池。
StrngBoot中则提供了很方便的方式执行异步调用。
按照官方示例开撸
代码入下
maven依赖:
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.3.RELEASE</version>
- </parent>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- </dependencies>
启动类:添加@EnableAsync注解
- @SpringBootApplication
- @EnableAsync
- public class Application{
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
- }
Controller
只需在需要异步执行方法上添加@Async注解
- @RestController
- @RequestMapping("")
- public class AsyncTaskController {
- @RequestMapping("")
- public String doTask() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- this.task1();
- this.task2();
- this.task3();
- long currentTimeMillis1 = System.currentTimeMillis();
- return "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
- }
- @Async
- public void task1() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(1000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- @Async
- public void task2() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(2000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- @Async
- public void task3() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(3000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- }
main函数运行spirngboot项目,启动完成后浏览器访问:
http://localhost:8080/
控制台:
- task1任务耗时:1012ms
- task2任务耗时:2009ms
- task3任务耗时:3004ms
等了一段浏览器时候输出入下:
- task任务总耗时:6002ms
异步并没有执行!
难道是代码写错了?反复检查了好几遍,并没有发现什么明显错误,想起spring对@Transactional注解时也有类似问题,spring扫描时具有@Transactional注解方法的类时,是生成一个代理类,由代理类去开启关闭事务,而在同一个类中,方法调用是在类体内执行的,spring无法截获这个方法调用。
豁然开朗,将异步任务单独放到一个类中,调整代码入下:
Controller
- @RequestMapping("")
- @RestController
- public class AsyncTaskController {
- @Autowired
- private AsyncTask asyncTask;
- @RequestMapping("")
- public String doTask() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- asyncTask.task1();
- asyncTask.task2();
- asyncTask.task3();
- long currentTimeMillis1 = System.currentTimeMillis();
- return "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
- }
- }
异步任务类
- @Component
- public class AsyncTask {
- @Async
- public void task1() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(1000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- @Async
- public void task2() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(2000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- @Async
- public void task3() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(3000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- }
- }
控制台:
- task1任务耗时:1012ms
- task2任务耗时:2009ms
- task3任务耗时:3004ms
访问浏览器结果入下:
- task任务总耗时:19ms
异步调用成功!
如何知道三个异步任务什么时候执行完,执行的结果怎样呢?可以采用添加Fature回调方式判断
代码入下:
异步任务类
- @Component
- public class AsyncTask {
- @Async
- public Future<String> task1() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(1000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task1任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- return new AsyncResult<String>("task1执行完毕");
- }
- @Async
- public Future<String> task2() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(2000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task2任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- return new AsyncResult<String>("task2执行完毕");
- }
- @Async
- public Future<String> task3() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Thread.sleep(3000);
- long currentTimeMillis1 = System.currentTimeMillis();
- System.out.println("task3任务耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms");
- return new AsyncResult<String>("task3执行完毕");
- }
- }
Controller
- @RequestMapping("")
- @RestController
- public class AsyncTaskController {
- @Autowired
- private AsyncTask asyncTask;
- @RequestMapping("")
- public String doTask() throws InterruptedException{
- long currentTimeMillis = System.currentTimeMillis();
- Future<String> task1 = asyncTask.task1();
- Future<String> task2 = asyncTask.task2();
- Future<String> task3 = asyncTask.task3();
- String result = null;
- for (;;) {
- if(task1.isDone() && task2.isDone() && task3.isDone()) {
- // 三个任务都调用完成,退出循环等待
- break;
- }
- Thread.sleep(1000);
- }
- long currentTimeMillis1 = System.currentTimeMillis();
- result = "task任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms";
- return result;
- }
- }
控制台输出:
- task1任务耗时:1000ms
- task2任务耗时:2001ms
- task3任务耗时:3001ms
浏览器输出:
- <span style="font-family:Simsun;font-size:14px;">task任务总耗时:4015ms</span>
异步调用成功,并且在所有任务都完成时程序才返回了结果!
SpringBoot集成篇(二) 异步调用Async的更多相关文章
- springboot:异步调用@Async
在后端开发中经常遇到一些耗时或者第三方系统调用的情况,我们知道Java程序一般的执行流程是顺序执行(不考虑多线程并发的情况),但是顺序执行的效率肯定是无法达到我们的预期的,这时就期望可以并行执行,常规 ...
- SpringBoot学习笔记(七):SpringBoot使用AOP统一处理请求日志、SpringBoot定时任务@Scheduled、SpringBoot异步调用Async、自定义参数
SpringBoot使用AOP统一处理请求日志 这里就提到了我们Spring当中的AOP,也就是面向切面编程,今天我们使用AOP去对我们的所有请求进行一个统一处理.首先在pom.xml中引入我们需要的 ...
- springboot:嵌套使用异步注解@Async还会异步执行吗
一.引言 在前边的文章<[springboot:使用异步注解@Async的那些坑>中介绍了使用@Async注解获取任务执行结果的错误用法,今天来分享下另外一种常见的错误. 二.代码演示 下 ...
- SpringBoot系列:Spring Boot异步调用@Async
在实际开发中,有时候为了及时处理请求和进行响应,我们可能会多任务同时执行,或者先处理主任务,也就是异步调用,异步调用的实现有很多,例如多线程.定时任务.消息队列等, 这一章节,我们就来讲讲@Async ...
- springboot 异步调用Async使用方法
引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3. ...
- springboot之异步调用@Async
原文:http://www.cnblogs.com/xuwenjin/p/8858050.html 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交 ...
- 170719、springboot编程之异步调用@Async
1.在pom.xml中增加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artif ...
- SpringBoot异步调用--@Async详解
1. 概述 在日常开发中,为了提高主线程的效率,往往需要采用异步调用处理,例如系统日志等.在实际业务场景中,可以使用消息中间件如RabbitMQ.RocketMQ.Kafka等来解决.假如对高可用 ...
- nodejs异步调用async
犹豫nodejs是异步编程模型,有一些在同步编程中很容易做到的事情,现在却变得很麻烦,async的流程控制就是为了简化这些操作var async = require('async'); 1.serie ...
随机推荐
- 2.纯 CSS 创作一个矩形旋转 loader 特效
原文地址:2.纯 CSS 创作一个矩形旋转 loader 特效 扩展后地址:https://scrimba.com/c/cNJVWUR 扩展地址:https://codepen.io/pen/ HT ...
- PHP获取照片exif信息
在这个没图说个屁的年代,照片还是很重要的.如果照片上传后会自动加上 照片相关信息,那用户体验的确会好很多,本着这个想法,今天尝试了下 PHP获取照片exif信息,重要的是 获取图片的GPS信息,如果再 ...
- Xshell使用
xshell更新之后窗口标题没了,多个窗口之后没法切换. 使用ctrl+shift+t恢复 ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
- Firemonkey 绘图 TPathData
Firemonkey TPathData TPath控件 procedure TForm12.FormPaint( Sender : TObject; Canvas : TCanvas; const ...
- 进程和创建线程的两种方法(threading.Thread)
进程 如QQ 要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理, 网络接口的调用等,进程就是各种资源管理的集合 线程:是操作系统最小的调度单位,是一串指令的结合 进程 要操作 ...
- UI5-文档-4-Walkthrough
在本教程中,我们将向您介绍SAPUI5的所有主要开发范例. 我们首先向您介绍基本的开发范例,如模型M-视图V-控制器C,并为我们的应用程序建立一个最佳实践结构.我们将以经典的“Hello World” ...
- nginx访问静态文件配置
通过nginx访问静态文件配置,均是在server模块中配置,有两种方式: 1.alias 通过alias关键字,重定义路径,如 server{ listen 7001; server ...
- 在Linux Bash通过上下键快速查找历史命令
在centos 7中 ~/.bashrc 或者Mac中的 ~/.bash_profile 中添加,然后source一下以下内容: if [[ $- == *i* ]] then bind '" ...
- 类定义,创建/销毁OC对象
类定义 1 OC类分为2个文件,一个是.h文件,一个是.m文件: 2 .h文件存放类.函数声明: 3 .m文件类的具体实现: 4 类声明使用关键字@interface.@end来声明: 5 类实现使用 ...
- redis启动.停止.重启
Linux下安装 ]# wget http://download.redis.io/releases/redis-2.8.17.tar.gz ]# tar xzf redis-2.8.17.tar.g ...