Spring Boot使用@Async实现异步调用
原文:http://blog.csdn.net/a286352250/article/details/53157822
项目GitHub地址 :
https://github.com/FrameReserve/TrainingBoot
Spring Boot(十)使用@Async实现异步调用 ,标记地址:
https://github.com/FrameReserve/TrainingBoot/releases/tag/0.0.10
Spring Boot启动类,增加@EnableAsync注解配置:
src/main/java/com/training/SpringBootServlet.java
- package com.training;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.boot.builder.SpringApplicationBuilder;
- import org.springframework.boot.web.support.SpringBootServletInitializer;
- import org.springframework.scheduling.annotation.EnableAsync;
- @SpringBootApplication
- @EnableAsync
- public class SpringBootServlet extends SpringBootServletInitializer {
- // jar启动
- public static void main(String[] args) {
- SpringApplication.run(SpringBootServlet.class, args);
- }
- // tomcat war启动
- @Override
- protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
- return application.sources(SpringBootServlet.class);
- }
- }
测试:
增加异步方法Service,线程休眠:
- package com.training.async.service.impl;
- import java.util.Random;
- import java.util.concurrent.Future;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.scheduling.annotation.AsyncResult;
- import org.springframework.stereotype.Service;
- import com.training.async.service.DemoAsyncService;
- @Service
- public class DemoAsyncServiceImpl implements DemoAsyncService {
- public static Random random =new Random();
- @Async
- public Future<String> doTaskOne() throws Exception {
- System.out.println("开始做任务一");
- long start = System.currentTimeMillis();
- Thread.sleep(random.nextInt(10000));
- long end = System.currentTimeMillis();
- System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");
- return new AsyncResult<>("任务一完成");
- }
- @Async
- public Future<String> doTaskTwo() throws Exception {
- System.out.println("开始做任务二");
- long start = System.currentTimeMillis();
- Thread.sleep(random.nextInt(10000));
- long end = System.currentTimeMillis();
- System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");
- return new AsyncResult<>("任务二完成");
- }
- @Async
- public Future<String> doTaskThree() throws Exception {
- System.out.println("开始做任务三");
- long start = System.currentTimeMillis();
- Thread.sleep(random.nextInt(10000));
- long end = System.currentTimeMillis();
- System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");
- return new AsyncResult<>("任务三完成");
- }
- }
调用异步测试测试,查看控制台输出执行顺序:
- package com.training.async.controller;
- import io.swagger.annotations.ApiOperation;
- import java.util.concurrent.Future;
- import javax.annotation.Resource;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseBody;
- import org.springframework.web.bind.annotation.RestController;
- import com.training.async.service.DemoAsyncService;
- import com.training.core.dto.ResultDataDto;
- @RestController
- @RequestMapping(value="/async")
- public class DemoAsyncController {
- @Resource
- private DemoAsyncService demoAsyncService;
- /**
- * 测试异步方法调用顺序
- */
- @ApiOperation(value="测试异步方法调用顺序", notes="getEntityById")
- @RequestMapping(value = "/getTestDemoAsync", method = RequestMethod.GET)
- public @ResponseBody ResultDataDto getEntityById() throws Exception {
- long start = System.currentTimeMillis();
- Future<String> task1 = demoAsyncService.doTaskOne();
- Future<String> task2 = demoAsyncService.doTaskTwo();
- Future<String> task3 = demoAsyncService.doTaskThree();
- while(true) {
- if(task1.isDone() && task2.isDone() && task3.isDone()) {
- // 三个任务都调用完成,退出循环等待
- break;
- }
- Thread.sleep(1000);
- }
- long end = System.currentTimeMillis();
- System.out.println("任务全部完成,总耗时:" + (end - start) + "毫秒");
- return ResultDataDto.addSuccess();
- }
- }
原文:http://blog.csdn.net/v2sking/article/details/72795742
什么是异步调用?
异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行。
如何实现异步调用?
多线程,这是很多人第一眼想到的关键词,没错,多线程就是一种实现异步调用的方式。
在非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>
异步调用成功,并且在所有任务都完成时程序才返回了结果!
Spring Boot使用@Async实现异步调用的更多相关文章
- Spring Boot使用@Async实现异步调用:自定义线程池
前面的章节中,我们介绍了使用@Async注解来实现异步调用,但是,对于这些异步执行的控制是我们保障自身应用健康的基本技能.本文我们就来学习一下,如果通过自定义线程池的方式来控制异步调用的并发. 定义线 ...
- spring boot中使用@Async实现异步调用任务
本篇文章主要介绍了spring boot中使用@Async实现异步调用任务,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 什么是“异步调用”? “异步调用”对应的是“同步 ...
- spring boot 学习(十一)使用@Async实现异步调用
使用@Async实现异步调用 什么是”异步调用”与”同步调用” “同步调用”就是程序按照一定的顺序依次执行,,每一行程序代码必须等上一行代码执行完毕才能执行:”异步调用”则是只要上一行代码执行,无需等 ...
- Spring Boot -- Spring Boot之@Async异步调用、Mybatis、事务管理等
这一节将在上一节的基础上,继续深入学习Spring Boot相关知识,其中主要包括@Async异步调用,@Value自定义参数.Mybatis.事务管理等. 本节所使用的代码是在上一节项目代码中,继续 ...
- Spring Boot中使用@Async实现异步调用
在Spring Boot中,我们只需要通过使用@Async注解就能简单的将原来的同步函数变为异步函数,为了让@Async注解能够生效,还需要在Spring Boot的主程序中配置@EnableAsyn ...
- 56. spring boot中使用@Async实现异步调用【从零开始学Spring Boot】
什么是"异步调用"? "异步调用"对应的是"同步调用",同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执 ...
- Spring Boot中使用@Async实现异步调用,加速任务的执行!
什么是"异步调用"?"异步调用"对应的是"同步调用",同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行 ...
- Spring @Async实现异步调用示例
什么是“异步调用”? “异步调用”对应的是“同步调用”,同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行:异步调用指程序在顺序执行时,不等待异步调用的语句返回结果 ...
- Spring Boot2.0之@Async实现异步调用
补充一个知识点: lombok底层原理使用的是: 字节码技术ASM修改字节码文件,生成比如类似于get() set( )方法 一定要在开发工具安装 在编译时候修改字节码文件(底层使用字节码技术),线上 ...
随机推荐
- centos7.6升级ssh7.9、安装PHP7.2、Nginx1.15.9、PHP加密扩展php_screw1.5
1.centos7 安装PHP7.2版本 #查询是否安装过php yum list installed | grep php yum provides php #移除php yum remove ph ...
- Ubuntu下kafka集群环境搭建及测试
kafka介绍: Kafka[1是一种高吞吐量[2] 的分布式发布订阅消息系统,有如下特性: 通过O(1)的磁盘数据结构提供消息的持久化,这种结构对于即使数以TB的消息存储也能够保持长时间的稳定性能 ...
- Drupal7所见即所得模块CKEditor
初学Drupal(7.26),刚好遇到一个需要用到CKEditor模块的项目,于是就摸索着把它给装上了. 图片上传出问题 回到Drupal7的管理页面后刚好发现了对于CKEditor的“状态报告”(错 ...
- COGS727 [网络流24题] 太空飞行计划
[问题描述] W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪 ...
- 网络流专题练习Day2
04/17 目前做了:题 由于目前六道都是1A感觉非常爽... BZOJ1412: [ZJOI2009]狼和羊的故事 “狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向 ...
- [BZOJ1602&BZOJ1787&BZOJ2144]树上LCA的算法巩固练习
简述求LCA的倍增算法 对于树上的所有节点,我们可以很轻松地通过dfs求出其直接的父亲节点以及其深度 通过类似RMQ的原理我们可以处理出每个节点的第2^i个父亲 //这个过程既可以在dfs之后双重循环 ...
- webstorm vue代码修改后不更新问题
把 safe write 的勾去掉就行了.
- python基础===正则表达式(转)
正则表达式是一个很强大的字符串处理工具,几乎任何关于字符串的操作都可以使用正则表达式来完成,作为一个爬虫工作者,每天和字符串打交道,正则表达式更是不可或缺的技能,正则表达式的在不同的语言中使用方式可能 ...
- scrapy的CrawlSpider使用
1.创建项目 我这里的项目名称为scrapyuniversal,然后我创建在D盘根目录.创建方法如下 打开cmd,切换到d盘根目录.然后输入以下命令: scrapy startproject scra ...
- hdu 1348(凸包)
Wall Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...