配置一个ExecutorService
@Configuration
@EnableAsync
public class BeanConfig {
@Bean
public ExecutorService getAsyncExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(7);
executor.setMaxPoolSize(42);
executor.setQueueCapacity(11);
executor.setThreadNamePrefix("async-executor-");
executor.initialize();
return executor.getThreadPoolExecutor();
}
}
编写
package com.huskyui.currencyspringinaction.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.*;
/**
* @author huskyui
* @date 2020/4/17 15:50
*/
@RestController
public class HelloController {
private Logger logger = LoggerFactory.getLogger(HelloController.class);
@Resource
private ExecutorService executorService;
@RequestMapping("/sync")
public String sync() {
long start = System.currentTimeMillis();
int resultA = 0,
resultB = 0;
try {
TimeUnit.SECONDS.sleep(2);
resultA = 2;
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
TimeUnit.SECONDS.sleep(1);
resultB = 1;
} catch (InterruptedException e) {
e.printStackTrace();
}
long cost = System.currentTimeMillis() - start;
logger.info("sync cost:{} result {}", cost, (resultA + resultB));
return String.valueOf(resultA + resultB);
}
@RequestMapping("/async")
public String async() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
int result = 0;
// Integer是futureA的返参类型
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> {
// 模拟工作1
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 2;
}, executorService);
CompletableFuture<Integer> futureB = CompletableFuture.supplyAsync(() -> {
// 模拟工作2
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1;
}, executorService);
CompletableFuture<Void> allFuture = CompletableFuture.allOf(futureA, futureB);
allFuture.join();
result = futureA.get() + futureB.get();
long cost = System.currentTimeMillis() - start;
logger.info("async cost:{} result {}", cost, result);
return String.valueOf(result);
}
}
测试
可以看到sync请求时,会耗时3秒,async请求,耗时2秒
感谢
阅读了一些其他人的博客,以及Netty交流群里面大佬传授
第二种写法
可以查看官方教程
使用@Async
注解
@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 purpose
Thread.sleep(1000L);
return CompletableFuture.completedFuture(results);
}
}
@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");
CompletableFuture<User> page4 = gitHubLookupService.findUser("huskyui");
// wait unit they are all done
CompletableFuture.allOf(page1, page2, page3, page4).join();
logger.info("Elapsed time: " + (System.currentTimeMillis() - start));
logger.info("-->" + page1.get());
logger.info("-->" + page2.get());
logger.info("-->" + page3.get());
logger.info("-->" + page4.get());
}
}
当然对于,任务的数量不定的话,可以使用
下面这张方式
@Override
public List<String> doTasks() throws InterruptedException, ExecutionException {
List<String> result = new ArrayList<>();
List<CompletableFuture<String>> completableFutureList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
completableFutureList.add(taskService.doSingleTask(i));
}
CompletableFuture<String>[] completableFutures = completableFutureList.toArray(new CompletableFuture[completableFutureList.size()]);
CompletableFuture.allOf(completableFutures).join();
for(CompletableFuture<String> future:completableFutures){
result.add(future.get());
}
return result;
}