zoukankan      html  css  js  c++  java
  • 【并发】基于 @Async和 CompletableFuture 实现并发异步操作

    参考链接:Spring官方示例

    User.java

    package hello;
    
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    
    @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 + "]";
        }
    
    }
    

    @Async

    1. 添加 @Async注解;
    2. 返回值声明为: CompletableFuture
    3. 配置 @Component 或 @ Service 等,保证可以 组件扫描到
    package hello;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.web.client.RestTemplateBuilder;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Service;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.concurrent.CompletableFuture;
    
    @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(1000L);
            return CompletableFuture.completedFuture(results);
        }
    
    }
    

    自定义 Executor(可选),并开启注解 @EnableAsync

    如果不配置,则使用默认的:SimpleAsyncTaskExecutor

    package hello;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.scheduling.annotation.EnableAsync;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    import java.util.concurrent.Executor;
    
    @SpringBootApplication
    @EnableAsync
    public class Application {
    
        public static void main(String[] args) {
            // close the application context to shut down the custom ExecutorService
            SpringApplication.run(Application.class, args).close();
        }
    
        @Bean
        public Executor asyncExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(2);
            executor.setMaxPoolSize(2);
            executor.setQueueCapacity(500);
            executor.setThreadNamePrefix("GithubLookup-");
            executor.initialize();
            return executor;
        }
    
    
    }
    

    获取并发执行结果

    package hello;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.stereotype.Component;
    
    import java.util.concurrent.CompletableFuture;
    
    @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());
    
        }
    
    }
    

    结果

    2016-09-01 10:25:21.295  INFO 17893 --- [ GithubLookup-2] hello.GitHubLookupService                : Looking up CloudFoundry
    2016-09-01 10:25:21.295  INFO 17893 --- [ GithubLookup-1] hello.GitHubLookupService                : Looking up PivotalSoftware
    2016-09-01 10:25:23.142  INFO 17893 --- [ GithubLookup-1] hello.GitHubLookupService                : Looking up Spring-Projects
    2016-09-01 10:25:24.281  INFO 17893 --- [           main] hello.AppRunner                          : Elapsed time: 2994
    2016-09-01 10:25:24.282  INFO 17893 --- [           main] hello.AppRunner                          : --> User [name=Pivotal Software, Inc., blog=http://pivotal.io]
    2016-09-01 10:25:24.282  INFO 17893 --- [           main] hello.AppRunner                          : --> User [name=Cloud Foundry, blog=https://www.cloudfoundry.org/]
    2016-09-01 10:25:24.282  INFO 17893 --- [           main] hello.AppRunner                          : --> User [name=Spring, blog=http://spring.io/projects]
    
  • 相关阅读:
    Linux安装nginx
    linux目录结构
    Django-admin
    celery
    Flask-Migrate
    Flask-Script
    Flask-SQLAlchemy
    SQLAlchemy
    mongodb的增删改查
    websocket的加密和解密过程
  • 原文地址:https://www.cnblogs.com/ssslinppp/p/7461732.html
Copyright © 2011-2022 走看看