同步和异步控制器的区别
同步控制器(Synchronous Controller):在同步控制器中,每个请求都在一个单独的线程中处理。当一个请求到达时,控制器会从请求中提取必要的信息并处理该请求,然后返回响应给客户端。在处理请求期间,线程会一直阻塞,直到请求处理完成为止。这种方式适用于简单的请求和响应,但在处理大量并发请求时可能会导致资源利用不足,因为每个请求都会阻塞一个线程,这可能会限制系统的伸缩性和性能。
异步控制器(Asynchronous Controller):在异步控制器中,每个请求都在一个单独的线程中启动,但该线程不会一直阻塞,而是在发起耗时操作之后立即释放控制权。控制器会返回一个CompletableFuture对象,该对象表示异步操作的结果。而不会直接返回响应给客户端。一旦异步操作完成,系统会通过一个独立的线程来处理该结果,并将响应返回给客户端。异步控制器可以提高系统的并发处理能力和响应性能,尤其在处理大量耗时操作的情况下更为有效。
区别:
- 同步控制器在处理请求期间,线程会一直阻塞,而异步控制器则可以释放线程,提高资源的利用效率。
- 异步控制器将响应的处理推迟到异步操作完成后,可以提高系统的并发处理能力和响应性能。
- 异步控制器需要使用CompletableFuture或其他异步编程方式来处理异步操作的结果。
实现异步非阻塞的 controller
要实现异步非阻塞的 controller,可以使用异步的请求处理方式和非阻塞的IO操作。
-
使用异步的请求处理方式:
在Spring MVC中,可以使用
@RequestMapping
注解的produces
属性指定 produces 为"application/json"
,然后使用@ResponseBody
注解将返回的结果直接写入 response 中,最后用DeferredResult
或CompletableFuture
来处理异步请求的结果。更推荐使用
CompletableFuture
, 因为它适配@ControllerAdvice
统一异常处理时来得更简单。
@RestController
public class MyController {
@GetMapping(value = "/api/example", produces = "application/json")
public CompletableFuture<ResponseEntity<String>> asyncExample() {
// 异步处理请求
CompletableFuture<ResponseEntity<String>> future = new CompletableFuture<>();
// 异步操作
CompletableFuture.supplyAsync(() -> {
// 执行异步操作
String result = performAsyncOperation();
return ResponseEntity.ok(result);
}).whenComplete((responseEntity, throwable) -> {
// 处理结果或异常
if (throwable != null) {
future.completeExceptionally(throwable);
} else {
future.complete(responseEntity);
}
});
return future;
}
private String performAsyncOperation() {
// 执行异步操作
return "Response from asynchronous operation";
}
}
关于CompletableFuture
的更多使用可以查看博客: java8 CompletableFuture 异步编程与任务编排
-
使用非阻塞的IO操作
可以使用非阻塞的操作如 NIO(非阻塞IO),或者使用类似于事件驱动的框架,如 Netty、Vert.x 等。
@RestController
public class MyController {
@GetMapping(value = "/api/example", produces = "application/json")
public void asyncExample(HttpServletRequest request, ServletResponse response) {
// 非阻塞IO操作,如使用NIO或事件驱动的框架
// 注册回调函数,处理请求
// 将处理结果写入 response
}
}
这样,通过使用异步请求处理和非阻塞IO操作,就可以实现异步非阻塞的 controller。
网友评论