我是Spring Boot的新手,想进一步了解DeferredResult和@Async方法。我在控制器中创建了一个方法,如下所示,它工作正常。
@GetMapping("/temp/{id}")
public DeferredResult<ResponseEntity<?>> findByIdTemp(@PathVariable Long id) throws InterruptedException {
System.out.println("Request received : "+Thread.currentThread().getName());
final DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>();
ForkJoinPool.commonPool().submit(() -> {
System.out.println("Processing in separate thread");
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
}
deferredResult.setResult(ResponseEntity.ok("ok"));
});
System.out.println("Thread freed : " +Thread.currentThread().getName());
return deferredResult;
}
下面是我收到的输出。
Request received : http-nio-8080-exec-1
Thread freed : http-nio-8080-exec-1
Processing in separate thread
然后我在服务类中创建了@Async方法,并在配置类中启用了异步。
@Configuration
@EnableAsync
public class ThreadPoolConfiguration {
@Autowired
private ExecutorConfiguration configuration;
@Bean(name = "threadPool")
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
threadPool.setCorePoolSize(configuration.getDnCallBackPoolSize());
return threadPool;
}
}
@Async("threadPool")
public Future<String> getResult() throws InterruptedException {
System.out.println("Separate thread : "+Thread.currentThread().getName());
Thread.sleep(6000);
return new AsyncResult<>("Success");
}
然后我从控制器类中调用了服务方法
@GetMapping("/temp/{id}")
public DeferredResult<ResponseEntity<?>> findByIdTemp(@PathVariable Long id) {
System.out.println("Request received : "+Thread.currentThread().getName());
final DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>();
ResponseDTO responseDTO = null;
try {
responseDTO = ResponseDTO.builder()
.status(HttpStatus.OK.toString())
.body(productService.getResult().get()).build();
ResponseEntity responseEntity = ResponseEntity.ok(responseDTO);
deferredResult.setResult(responseEntity);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
} catch (ExecutionException e) {
System.out.println(e.getMessage());
}
System.out.println("Thread freed : " +Thread.currentThread().getName());
return deferredResult;
}
但是我得到的结果与众不同
Request received : http-nio-8080-exec-1
Separate thread : dnCallBackPool-1
Thread freed : http-nio-8080-exec-1
似乎控制器方法正在等待服务方法的响应。谁能告诉我如何通过@Async方法正确使用DeferredResult。
答案 0 :(得分:0)
似乎控制器方法正在等待服务方法的响应。
是的,控制器方法正在等待productService
的响应,因为来自@Async
的{{1}}线程仅负责执行dnCallBackPool
中的getResult()
方法
但是productService
块中的代码是由Web容器线程(例如try-catch
)执行的
http-nio-8080-exec-1
responseDTO = ResponseDTO.builder()
.status(HttpStatus.OK.toString())
.body(productService.getResult()**.get()**).build();
上的Future
对象get()调用是阻塞调用,当前线程应等待productService.getResult()
线程完成处理并返回结果
在必要时等待计算完成,然后检索其结果。
在控制器方法末尾的@Async
对象上的get()
上也是如此,这样两个方法都可以并行执行,下面是一个示例
控制器:
Future
服务:
@GetMapping("/temp/{id}")
public DeferredResult<ResponseEntity<?>> findByIdTemp(@PathVariable Long id) {
System.out.println("Request received : "+Thread.currentThread().getName());
final DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>();
Future<String> future = productService.getResult(); //Async call to service method
System.out.println("Current Thread Execution: " +Thread.currentThread().getName()); // Execute parallely and print this line immediately
ResponseDTO responseDTO = null;
try {
responseDTO = ResponseDTO.builder()
.status(HttpStatus.OK.toString())
.body(future.get()).build(); // current thread waits for result
System.out.println("Thread freed : " +Thread.currentThread().getName()); // This line prints as soon as service tasks completes
ResponseEntity responseEntity = ResponseEntity.ok(responseDTO);
deferredResult.setResult(responseEntity);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
} catch (ExecutionException e) {
System.out.println(e.getMessage());
}
return deferredResult;