20.异步方法

  1. 构建
    1. 编码
      1. 创建实体类
      2. 创建请求的service
      3. 开启异步任务:
    2. 测试
      1. 官网地址
      2. 问题1:

构建

IDEA新建项目 选择 Web
或者POM引入

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</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 + "]";
    }

}
创建请求的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 CompletableFuture<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(10000L);
        return CompletableFuture.completedFuture(results);
    }

}

通过,RestTemplate去请求,另外加上类@Async 表明是一个异步任务。

开启异步任务:
@SpringBootApplication
@EnableAsync
public class SpringbootAsyncApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootAsyncApplication.class, args);
    }

    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("GithubLookup-");
        executor.initialize();
        return executor;
    }
}

@EnableAsync 注释 开启Spring 运行 @Async的后台线程池
将并发线程限制为两个,队列大小限制为500个

测试

创建测试类

@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
        CompletableFuture<User> page1 = gitHubLookupService.findUser("PivotalSoftware");
        CompletableFuture<User> page2 = gitHubLookupService.findUser("CloudFoundry");
        CompletableFuture<User> page3 = gitHubLookupService.findUser("Spring-Projects");

        // Wait until they are all done
        CompletableFuture.allOf(page1,page2,page3).join();

        // Print results, including elapsed time
        logger.info("Elapsed time: " + (System.currentTimeMillis() - start));
        logger.info("--> " + page1.get());
        logger.info("--> " + page2.get());
        logger.info("--> " + page3.get());

    }

}

启动程序,控制台打印如下

2020-03-15 20:43:26.744  INFO 1656 --- [ GithubLookup-2] c.x.s.service.GitHubLookupService        : Looking up CloudFoundry
2020-03-15 20:43:26.744  INFO 1656 --- [ GithubLookup-1] c.x.s.service.GitHubLookupService        : Looking up PivotalSoftware
2020-03-15 20:43:38.077  INFO 1656 --- [ GithubLookup-1] c.x.s.service.GitHubLookupService        : Looking up Spring-Projects
2020-03-15 20:43:49.247  INFO 1656 --- [           main] com.xiaofine.springbootasync.AppRunner   : Elapsed time: 22515
2020-03-15 20:43:49.247  INFO 1656 --- [           main] com.xiaofine.springbootasync.AppRunner   : --> User [name=Pivotal Software, Inc., blog=http://pivotal.io]
2020-03-15 20:43:49.247  INFO 1656 --- [           main] com.xiaofine.springbootasync.AppRunner   : --> User [name=Cloud Foundry, blog=https://www.cloudfoundry.org/]
2020-03-15 20:43:49.247  INFO 1656 --- [           main] com.xiaofine.springbootasync.AppRunner   : --> User [name=Spring, blog=https://spring.io/projects]
2020-03-15 20:43:49.249  INFO 1656 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'taskExecutor'

可以卡的前面2个方法分别在GithubLookup-1 和GithubLookup-2执行,第三个在GithubLookup-2执行,注意因为在配置线程池的时候最大线程为2.如果你把线程池的个数为3的时候,耗时减少。

如果去掉@Async,你会发现,执行这三个方法都在main线程中执行。耗时总结,如下:

2020-03-15 20:47:17.499  INFO 8256 --- [           main] c.x.s.service.GitHubLookupService        : Looking up PivotalSoftware
2020-03-15 20:47:29.058  INFO 8256 --- [           main] c.x.s.service.GitHubLookupService        : Looking up CloudFoundry
2020-03-15 20:47:40.204  INFO 8256 --- [           main] c.x.s.service.GitHubLookupService        : Looking up Spring-Projects
2020-03-15 20:47:51.380  INFO 8256 --- [           main] com.xiaofine.springbootasync.AppRunner   : Elapsed time: 33881
2020-03-15 20:47:51.380  INFO 8256 --- [           main] com.xiaofine.springbootasync.AppRunner   : --> User [name=Pivotal Software, Inc., blog=http://pivotal.io]
2020-03-15 20:47:51.380  INFO 8256 --- [           main] com.xiaofine.springbootasync.AppRunner   : --> User [name=Cloud Foundry, blog=https://www.cloudfoundry.org/]
2020-03-15 20:47:51.380  INFO 8256 --- [           main] com.xiaofine.springbootasync.AppRunner   : --> User [name=Spring, blog=https://spring.io/projects]
2020-03-15 20:47:51.382  INFO 8256 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'taskExecutor'
官网地址

https://spring.io/guides/gs/async-method/

问题1:

原本官方示例是如下,会报错Connect Reset 可能是提供的api限制

Thread.sleep(1000L);

调大十倍就没问题了

Thread.sleep(10000L);

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。

文章标题:20.异步方法

本文作者:xiaofine

发布时间:2020-03-21, 21:47:58

最后更新:2020-03-22, 08:22:32

原始链接:https://xiaofine1122.github.io/2020/03/21/20.%E5%BC%82%E6%AD%A5%E6%96%B9%E6%B3%95/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录