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 ...
随机推荐
- 1.纯 CSS 创作一个按钮文字滑动特效 + 弹幕(残缺)
原文地址:1# 视频演示如何用纯 CSS 创作一个按钮文字滑动特效 扩展后地址:https://scrimba.com/c/cJkzMfd HTML代码: <html> <head& ...
- 返回标签数据示例 (PHP)
标签接口函数 获取标签数据 array uc_tag_get(string tagname [, array nums]) 函数参数 参数 含义 string tagname 标签名称 array n ...
- leetcode179
class Solution { public: string largestNumber(vector<int>& nums) { int n=nums.size(); vect ...
- 安装新操作系统 Windows 路径设置 节省C盘空间
1.QQ个人文件夹设置到D盘,D:\ProgramData\QQ 2.IE收藏夹设置到D盘,IE缓存设置到D盘 例如我想把收藏夹默认的保存路径改到D:\study下.关闭Internet Explor ...
- gradle问题 cordova
cordova升级7.0后,运行 > ionic build android 或者 cordova build android 报出错误 Error: Could not find a ...
- 14 MySQL--事务&函数与流程控制
一.事务 事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性. 一堆sql语句:要么同时执行成功,要么同时失败 # 事务的原子性 场景: ...
- ABAP-关于 LUW
转载:https://www.cnblogs.com/liaojunbo/archive/2011/07/12/2103554.html 假设MAIN PROGRAM(调用程序)为MAIN,其所在的为 ...
- iOS 真机调试 Xcode 显示 device Error: device unavailable
一般来说有两个原因: 1. iphone没有加到test device里,将iphone的设备id加到test device列表里 2. Xcode不支持当前的iOS版本,将Xcode升级到最新版
- express + mongodb 搭建一个简易网站 (五)
前面已经将导航中的“所有宝贝”页面连上了mongodb,现在我们就把其他的页面脸上数据库,将整个网站全部实现. 打开routes文件,找到jacket.js,将里面的代码修改如下: var expre ...
- topGO
前面我们讲过GO.db这个包,现在接着延伸topGO包,该包是用来协助GO富集分析 1)安装 if("topGO" %in% rownames(installed.packages ...