【并发】基于 @Async和 CompletableFuture 实现并发异步操作
2017-09-01 09:45
411 查看
参考链接:Spring官方示例
返回值声明为: CompletableFuture
配置 @Component 或 @ Service 等,保证可以 组件扫描到
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
添加 @Async注解;返回值声明为: CompletableFuture
配置 @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
如果不配置,则使用默认的:SimpleAsyncTaskExecutorpackage 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]
相关文章推荐
- 57-005-3 bootstrap实现一个简单的项目案例--新闻操作(基于jsp无刷新异步操作)
- php curl批处理实现可控并发异步操作示例
- 基于APM模式的异步实现及跨线程操作窗体或控件方法的实现示例
- [置顶] Redis应用3-基于Redis消息队列实现的异步操作
- 使用AFNetworking3.0实现接口异步并发
- AJAX实现购物车的异步请求操作
- 基于MapX的GIS动态操作与实现
- java基于poi实现快速操作Excel的工具[v2.0.0]
- 前端通过AJAX提交数据,后台PHP处理数据实现异步操作基本流程
- 一种基于Qt的可伸缩的全异步C/S架构服务器实现(三) 流水线结构线程池设计
- 基于SEDA的异步框架设计与实现
- 基于C#的Socket编程的TCP异步实现
- 基于SpringMVC+Bootstrap实现图片异步上传进度显示
- 基于Hibernate Envers实现数据审计Audit操作记录
- Entity Framework 实体框架的形成之旅--基类接口的统一和异步操作的实现(3)
- 使用redux-thunk实现异步操作的中止
- 10.2 NSOperation/NSOperationQueue:提供了一些在GCD中不容易实现的特性,如:限制最大并发数量,操作之间的依赖关系.
- java多线程-专题-聊聊并发(五)原子操作的实现原理
- 异步窗体实现操作进度(ProgressWindow)
- 基于Spring的AspectJ操作日志实现