目录
0. 摘要
1. Callable
1.1 使用方法
1.2 测试结果
编辑
2. WebAsyncTask
2.1 使用方法
2.2 测试结果
3. DeferredResult
3.1 使用方法
3.2 测试结果
4. @Async
4.1 使用方法
4.2 测试结果
SpringBoot Controller异步返回,避免主干线程阻塞,主要有三类方法,分别是 Callble、WebAsyncTask和DeferredResult, @Async测试异步执行后,结果无法返回
@RequestMapping("asyncCallable/{param}")
public Callable asyncCallable(@PathVariable("param") String param){
log.info("asyncCallable controller start:{}", Thread.currentThread().getName());
Callable call = new Callable() {
@Override
public String call() throws Exception {
log.info("asyncCallable call start:{}", Thread.currentThread().getName());
Thread.sleep(100000);
log.info("asyncCallable call end:{}", Thread.currentThread().getName());
return String.format("asynCallable %s:%s", param, new Date());
}
};
log.info("asyncCallable controller end:{}", Thread.currentThread().getName());
return call;
}
异步响应,callable专用线程处理,主干线程不阻塞
@RequestMapping("asyncWebAsyncTask/{param}")
public WebAsyncTask asyncWebAsyncTask(@PathVariable("param") String param){
log.info("asyncWebAsyncTask controller start:{}", Thread.currentThread().getName());
WebAsyncTask task = new WebAsyncTask<>(60 * 1000l, new Callable() {
@Override
public String call() throws Exception {
log.info("asyncWebAsyncTask call start:{}", Thread.currentThread().getName());
Thread.sleep(30000);
log.info("asyncWebAsyncTask call end:{}", Thread.currentThread().getName());
return String.format("asynCallable %s:%s", param, new Date());
}
});
task.onTimeout(new Callable() {
@Override
public String call() throws Exception {
log.warn(param +":timeOut");
return param + ":timeOut";
}
});
task.onCompletion(new Runnable() {
@Override
public void run() {
log.info(param +":complete");
}
});
log.info("asyncWebAsyncTask controller end:{}", Thread.currentThread().getName());
return task;
}
主干线程不阻塞,异步处理
@RequestMapping("deferredResult/{param}")
public DeferredResult deferredResult(@PathVariable("param") String param){
log.info("deferredResult controller start:{}", Thread.currentThread().getName());
DeferredResult result = new DeferredResult<>();
new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
log.info("deferredResult call start:{}", Thread.currentThread().getName());
Thread.sleep(100000);
result.setResult(param +":deferredResult");
log.info("deferredResult call end:{}", Thread.currentThread().getName());
}
}).start();
log.info("deferredResult controller end:{}", Thread.currentThread().getName());
return result;
}
// controller method
@Autowired
AsyncService asyncService;
@RequestMapping("async/{param}")
public String async(@PathVariable("param") String param) throws InterruptedException {
log.info("asyncService controller start:{}", Thread.currentThread().getName());
String result = asyncService.asyncService(param);
log.info("asyncService controller end:{}", Thread.currentThread().getName());
return result;
}
@Asyn Service类
package com.example.springboottest.async;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
@Slf4j
@Component
public class AsyncService {
@Async
public String asyncService(@PathVariable("param") String param) throws InterruptedException {
log.info("asyncService call start:{}", Thread.currentThread().getName());
Thread.sleep(10000);
log.info("asyncService call end:{}", Thread.currentThread().getName());
return param +":async";
}
}
@Async 需要添加注解支持启用异步功能
package com.example.springboottest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
// main 入口添加@EnableAsync
@EnableAsync
@SpringBootApplication
public class SpringBootTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootTestApplication.class, args);
}
}
不等待@Async返回,直接返回结果,controller无法获取响应结果
5. 完成controller类
package com.example.springboottest.async;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.WebAsyncTask;
import java.util.Date;
import java.util.concurrent.Callable;
@RestController
@RequestMapping("/async")
@Slf4j
public class AsyncController {
@RequestMapping("asyncCallable/{param}")
public Callable asyncCallable(@PathVariable("param") String param){
log.info("asyncCallable controller start:{}", Thread.currentThread().getName());
Callable call = new Callable() {
@Override
public String call() throws Exception {
log.info("asyncCallable call start:{}", Thread.currentThread().getName());
Thread.sleep(100000);
log.info("asyncCallable call end:{}", Thread.currentThread().getName());
return String.format("asynCallable %s:%s", param, new Date());
}
};
log.info("asyncCallable controller end:{}", Thread.currentThread().getName());
return call;
}
@RequestMapping("asyncWebAsyncTask/{param}")
public WebAsyncTask asyncWebAsyncTask(@PathVariable("param") String param){
log.info("asyncWebAsyncTask controller start:{}", Thread.currentThread().getName());
WebAsyncTask task = new WebAsyncTask<>(60 * 1000l, new Callable() {
@Override
public String call() throws Exception {
log.info("asyncWebAsyncTask call start:{}", Thread.currentThread().getName());
Thread.sleep(30000);
log.info("asyncWebAsyncTask call end:{}", Thread.currentThread().getName());
return String.format("asynCallable %s:%s", param, new Date());
}
});
task.onTimeout(new Callable() {
@Override
public String call() throws Exception {
log.warn(param +":timeOut");
return param + ":timeOut";
}
});
task.onCompletion(new Runnable() {
@Override
public void run() {
log.info(param +":complete");
}
});
log.info("asyncWebAsyncTask controller end:{}", Thread.currentThread().getName());
return task;
}
@RequestMapping("deferredResult/{param}")
public DeferredResult deferredResult(@PathVariable("param") String param){
log.info("deferredResult controller start:{}", Thread.currentThread().getName());
DeferredResult result = new DeferredResult<>();
new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
log.info("deferredResult call start:{}", Thread.currentThread().getName());
Thread.sleep(100000);
result.setResult(param +":deferredResult");
log.info("deferredResult call end:{}", Thread.currentThread().getName());
}
}).start();
log.info("deferredResult controller end:{}", Thread.currentThread().getName());
return result;
}
@Autowired
AsyncService asyncService;
@RequestMapping("async/{param}")
public String async(@PathVariable("param") String param) throws InterruptedException {
log.info("asyncService controller start:{}", Thread.currentThread().getName());
String result = asyncService.asyncService(param);
log.info("asyncService controller end:{}", Thread.currentThread().getName());
return result;
}
}