SpringBoot非官方教程 | 第二十三篇: 异步方法
转载请标明出处:
原文首发于https://www.fangzhipeng.com/springboot/2017/07/11/springboot-ansy/
本文出自方志朋的博客
这篇文章主要介绍在springboot 使用异步方法,去请求github api.
创建工程
在pom文件引入相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
创建一个接收数据的实体:
@JsonIgnoreProperties(ignoreUnknown=true)
public class User {
private String name;
private String blog;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBlog() {
return blog;
}
public void setBlog(String blog) {
this.blog = blog;
}
@Override
public String toString() {
return "User [name=" + name + ", blog=" + blog + "]";
}
}
创建一个请求的 githib的service:
@Service
public class GitHubLookupService {
private static final Logger logger = LoggerFactory.getLogger(GitHubLookupService.class);
private final RestTemplate restTemplate;
public GitHubLookupService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
@Async
public Future<User> findUser(String user) throws InterruptedException {
logger.info("Looking up " + user);
String url = String.format("https://api.github.com/users/%s", user);
User results = restTemplate.getForObject(url, User.class);
// Artificial delay of 1s for demonstration purposes
Thread.sleep(1000L);
return new AsyncResult<>(results);
}
}
通过,RestTemplate去请求,另外加上类@Async 表明是一个异步任务。
开启异步任务:
@SpringBootApplication
@EnableAsync
public class Application extends AsyncConfigurerSupport {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("GithubLookup-");
executor.initialize();
return executor;
}
}
通过@EnableAsync开启异步任务;并且配置AsyncConfigurerSupport,比如最大的线程池为2.
测试
测试代码如下:
@Component
public class AppRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(AppRunner.class);
private final GitHubLookupService gitHubLookupService;
public AppRunner(GitHubLookupService gitHubLookupService) {
this.gitHubLookupService = gitHubLookupService;
}
@Override
public void run(String... args) throws Exception {
// Start the clock
long start = System.currentTimeMillis();
// Kick of multiple, asynchronous lookups
Future<User> page1 = gitHubLookupService.findUser("PivotalSoftware");
Future<User> page2 = gitHubLookupService.findUser("CloudFoundry");
Future<User> page3 = gitHubLookupService.findUser("Spring-Projects");
// Wait until they are all done
while (!(page1.isDone() && page2.isDone() && page3.isDone())) {
Thread.sleep(10); //10-millisecond pause between each check
}
// Print results, including elapsed time
logger.info("Elapsed time: " + (System.currentTimeMillis() - start));
logger.info("--> " + page1.get());
logger.info("--> " + page2.get());
logger.info("--> " + page3.get());
}
}
启动程序,控制台会打印:
2017-04-30 13:11:10.351 INFO 1511 — [ GithubLookup-1] com.forezp.service.GitHubLookupService : Looking up PivotalSoftware
2017-04-30 13:11:10.351 INFO 1511 — [ GithubLookup-2] com.forezp.service.GitHubLookupService : Looking up CloudFoundry
2017-04-30 13:11:13.144 INFO 1511 — [ GithubLookup-2] com.forezp.service.GitHubLookupService : Looking up Spring-Projects
耗时:3908
分析:可以卡的前面2个方法分别在GithubLookup-1 和GithubLookup-2执行,第三个在GithubLookup-2执行,注意因为在配置线程池的时候最大线程为2.如果你把线程池的个数为3的时候,耗时减少。
如果去掉@Async,你会发现,执行这三个方法都在main线程中执行。耗时总结,如下:
2017-04-30 13:13:00.934 INFO 1527 — [ main] com.forezp.service.GitHubLookupService : Looking up PivotalSoftware
2017-04-30 13:13:03.571 INFO 1527 — [ main] com.forezp.service.GitHubLookupService : Looking up CloudFoundry
2017-04-30 13:13:04.865 INFO 1527 — [ main] com.forezp.service.GitHubLookupService : Looking up Spring-Projects
耗时:5261
通过这一个小的栗子,你应该对异步任务有了一定的了解。
参考资料
https://spring.io/guides/gs/async-method/
源码下载
https://github.com/forezp/SpringBootLearning
优秀文章推荐:
- 更多springboot 教程:springBoot非官方教程 | 文章汇总
- 更多springcoud 教程:史上最简单的 SpringCloud 教程 | 文章汇总
扫码关注公众号有惊喜
(转载本站文章请注明作者和出处 方志朋的博客)
SpringBoot非官方教程 | 第二十三篇: 异步方法的更多相关文章
- SpringBoot非官方教程 | 第二十篇: 处理表单提交
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot-form/ 本文出自方志朋的博客 这篇文件主要介 ...
- SpringBoot非官方教程 | 第十三篇:springboot集成spring cache
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot13-springcache/ 本文出自方志朋的博 ...
- SpringBoot非官方教程 | 第二十一篇: springboot集成JMS
转载请标明出处: http://blog.csdn.net/forezp/article/details/71024024 本文出自方志朋的博客 springboot对JMS提供了很好的支持,对其做了 ...
- (转) SpringBoot非官方教程 | 第二十四篇: springboot整合docker
这篇文篇介绍,怎么为 springboot程序构建一个Docker镜像.docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源.Docker 可以让开发者打包他们的 ...
- SpringBoot非官方教程 | 第二十六篇: sprinboot整合elk,搭建实时日志平台
转载请标明出处: 原文首发于https://www.fangzhipeng.com/springboot/2017/07/11/sprinboot25-elk/ 本文出自方志朋的博客 这篇文章主要介绍 ...
- SpringBoot非官方教程 | 第二十四篇: springboot整合docker
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot24-docker/ 本文出自方志朋的博客 这篇文 ...
- SpringBoot非官方教程 | 第二十二篇: 创建含有多module的springboot工程
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springbot22-modules/ 本文出自方志朋的博客 这篇文 ...
- (转) SpringBoot非官方教程 | 第二篇:Spring Boot配置文件详解
springboot采纳了建立生产就绪spring应用程序的观点. Spring Boot优先于配置的惯例,旨在让您尽快启动和运行.在一般情况下,我们不需要做太多的配置就能够让spring boot正 ...
- (转)SpringBoot非官方教程 | 第七篇:springboot开启声明式事务
springboot开启事务很简单,只需要一个注解@Transactional 就可以了.因为在springboot中已经默认对jpa.jdbc.mybatis开启了事事务,引入它们依赖的时候,事物就 ...
随机推荐
- python之高阶函数map/reduce
L = [] for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]: L.append(f(n)) print(L) Python内建了map()和reduce()函数. 我们先看 ...
- C++里创建 Trie字典树(中文词典)(三)(联想)
萌新做词典第三篇,做得不好,还请指正,谢谢大佬! 今天把词典的联想做好了,也是比较low的,还改了之前的查询.遍历等代码. Orz 一样地先放上运行结果: test1 ID : char : 件 w ...
- mpvue自定义化后台富文本样式
最近公司写小程序开始换框架了,之前用wepy,现在用mpvue. mpvue是基于vue的写法来开发微信小程序.虽然不完全和vue一样,但是大致和vue一样,所以基本开发上是上手很快的. 现在项目进程 ...
- 元类(metaclass)
一.储备知识exec 储备知识exec:有下面三个参数 参数一:字符串形式的命令 参数二:全局作用域(字典形式),如果不指定默认使用globals() 参数三:局部作用域(字典形式),如果不指定默认就 ...
- MySQL 修改数据表中的字段的字符编码
1.查询 MySQL 的版本: SELECT VERSION(); 2.查询 MySQL 当前使用的字符集: SHOW VARIABLES LIKE '%character%'; 3.查询指定数据库的 ...
- 我为什么不用Django而用Flask?
前言 对于初学者来说,找到一个好的框架来学习或者项目开发都是非常有必要的,而当你有一定开发经验后,你应该选择适合当前业务需要的框架.我这里并不想探讨哪个框架好哪个不好,这个永恒的话题就跟探讨“世界上哪 ...
- ArcGIS图框生成和批量打印工具 5.2支持国家2000坐标系,支持ArcGIS10.1、ArcGIS10.2,输出图片可以是TIF和JPG
主要两个功能有:生成图框.批量输出MXD和JPG http://files.cnblogs.com/gisoracle/ScalePrint.rar 1. 批量生成标准分幅图或行政区划, ...
- Linux 一直提示 login incorrect
- 【PIC单片机】MPLAB X IDE快速入门指南
引言:近期由于项目实践需要,开始动手学习相关硬件知识.从PIC单片机入手. 单片机学习核心要点:查数据手册 配置寄存器 一.基于MPLAB X IDE配置位设置 MPLAB X IDE和MPLAB I ...
- day01-struts框架
一.框架概述 1.框架的意义与作用: 所谓框架,就是把一些繁琐的重复性代码封装起来,使程序员在编码中把更多的经历放到业务需求的分析和理解上面. 特点:封装了很多细节,程序员在使用的时候会非常简单. 2 ...