The introduction
When you think of asynchrony, synchronization is the first thing that comes to mind. So let’s start with what is synchronization? Synchronization is when a function call is made that does not return or continue until the result is received. Simply put, synchronization means that you have to do one thing at a time and wait until the previous one is done before you can do the next one. Asynchrony: Asynchrony, on the other hand, returns the call directly after it is made, without waiting for a result.
Browser synchronization
The browser initiates a request and waits for a response, during which time it blocks. * * such as early we when we are around electric business platform to buy things we open a product page, a flowchart is possible so, open up a page every time, is by a thread from the beginning to the end, the request to the database access to the inventory what commodity prices return to the page, also need to call third-party interface, For example, the coupon interface and so forth, we wait until all of this is done before the thread responds to the browser, and the thread just waits and waits and does nothing. This will not have a certain performance problem. The general process is as follows:
Browser asynchrony
In order to solve the problem of synchronization blocking, a new feature has been provided since the release of Servlet3.0: processing requests asynchronously. For example, when we enter the product details page, this front end will initiate a request, and then there will be a thread to execute the request, this request needs to go to the database to query inventory, call the third-party interface to query coupons, etc. The thread doesn’t have to wait. It’s done here, ready to move on to the next task. When the query database and third-party interface query coupons have results, a new thread will return the processing results to the front end. In this case, threads are not super saturated and need to work all the time without giving a chance to rest.
- This asynchrony is pure back-end asynchrony, insensitive to the front end, and does not result in an optimization in response time. But once our request thread (Tomcat thread) is an asynchronous servlet, we can immediately return and business-dependent tasks can be executed by the business thread. That is, the Tomcat thread can be reclaimed immediately. By default, Tomcat’s core thread is 10. The maximum number of threads is 200. We can recycle threads in a timely manner, which means we can handle more requests and increase our throughput, which is the main purpose of asynchronous servlets.
Let’s take a look at several asynchronous ways Spring MVC worksDocs. Spring. IO/spring – fram… Before we do that, let’s briefly review Servlet 3.1 asynchrony:
- The client (browser, app) sends a request
- The Servlet container allocates a thread to process a Servlet in the container
- The servlet calls Request.startAsync () to start asynchronous mode, saves AsyncContext, and returns.
- The servlet request thread and all filters can terminate, but its response will wait for the asynchronous thread to finish processing before returning.
- Other threads use the saved AsyncContext to complete the response
- The client receives a response. Procedure
Callable
/** Public id: Java finance * uses Callable *@return* /
@GetMapping("callable")
public Callable<String> callable(a) {
System.out.println(LocalDateTime.now().toString() + "-- > Main thread starts");
Callable<String> callable = () -> {
String result = "return callable";
// The service execution takes 5 seconds
Thread.sleep(5000);
System.out.println(LocalDateTime.now().toString() + "-- > Subtask thread ("+Thread.currentThread().getName()+")");
return result;
};
System.out.println(LocalDateTime.now().toString() + "-- > End of main thread");
return callable;
}
public static String doBusiness(a) {
// Service execution takes 10 seconds
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return UUID.randomUUID().toString();
}
Copy the code
- The controller first returns a Callable object
- Spring MVC starts asynchronous processing and submits the Callable object to a separate thread’s executor, TaskExecutor
- The DispatcherServlet and all filters exit the Servlet container thread, but the method’s response object is still not returned
- The Callable object eventually produces a return result, at which point Spring MVC redispatches the request back to the Servlet container to resume processing
- The DispatcherServlet is called again to resume processing of the results returned by the Callable asynchronous processing
We know SpringMvc can return JSON format data, or return view pages (HTML, JSP), etc. SpringMvc is how to achieve this? Is one of the main core class org. Springframework. Web. Method. Support. HandlerMethodReturnValueHandler let’s take a look at this class, this class is an interface, a total of two methods;
boolean supportsReturnType(MethodParameter returnType);
void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
Copy the code
The above our request is to return Callable such an outcome, we will according to the type of the returned to find all realized HandlerMethodReturnValueHandler this interface implementation class, In the end we will according to the method return type by supportsReturnType this find a corresponding HandlerMethodReturnValueHandler implementation class, We according to the return type is a Callable and then found the implementation class CallableMethodReturnValueHandler.To enable asynchronous threads, that is, in the handleReturnValue method. If you are interested, you can start debugging or better debugging.
CompletableFuture and ListenableFuture
@GetMapping("completableFuture")
public CompletableFuture<String> completableFuture(a) {
Thread pools are not normally placed here. Static declarations are used, just for demonstration purposes
ExecutorService executor = Executors.newCachedThreadPool();
System.out.println(LocalDateTime.now().toString() + "-- > Main thread starts");
CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(IndexController::doBusiness, executor);
System.out.println(LocalDateTime.now().toString() + "-- > End of main thread");
return completableFuture;
}
@GetMapping("listenableFuture")
public ListenableFuture<String> listenableFuture(a) {
Thread pools are not normally placed here. Static declarations are used, just for demonstration purposes
ExecutorService executor = Executors.newCachedThreadPool();
System.out.println(LocalDateTime.now().toString() + "-- > Main thread starts");
ListenableFutureTask<String> listenableFuture = new ListenableFutureTask<>(()-> doBusiness());
executor.execute(listenableFuture);
System.out.println(LocalDateTime.now().toString() + "-- > End of main thread");
return listenableFuture;
}
Copy the code
Note: Do not use the built-in ForkJoinPool thread pool. Create your own thread pool or you will have performance problems
WebAsyncTask
@GetMapping("asynctask")
public WebAsyncTask asyncTask(a) {
SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
System.out.println(LocalDateTime.now().toString() + "-- > Main thread starts");
WebAsyncTask<String> task = new WebAsyncTask(1000L, executor, ()-> doBusiness());
task.onCompletion(()->{
System.out.println(LocalDateTime.now().toString() + "-- > Call complete");
});
task.onTimeout(()->{
System.out.println("onTimeout");
return "onTimeout";
});
System.out.println(LocalDateTime.now().toString() + "-- > End of main thread");
return task;
}
Copy the code
DeferredResult
@GetMapping("deferredResult")
public DeferredResult<String> deferredResult(a) {
System.out.println(LocalDateTime.now().toString() + "-- > < span style = "max-width: 100%;+Thread.currentThread().getName()+")");
DeferredResult<String> deferredResult = new DeferredResult<>();
CompletableFuture.supplyAsync(()-> doBusiness(), Executors.newFixedThreadPool(5)).whenCompleteAsync((result, throwable)->{
if(throwable! =null) {
deferredResult.setErrorResult(throwable.getMessage());
}else{ deferredResult.setResult(result); }});// Called when an asynchronous request times out
deferredResult.onTimeout(()->{
System.out.println(LocalDateTime.now().toString() + "--->onTimeout");
});
// called after the asynchronous request completes
deferredResult.onCompletion(()->{
System.out.println(LocalDateTime.now().toString() + "--->onCompletion");
});
System.out.println(LocalDateTime.now().toString() + "-- > < span style = "max-width: 100%;+Thread.currentThread().getName()+End ")");
return deferredResult;
}
Copy the code
- All of the above asynchronous methods will wait until the doBusiness execution (10s) before sending the response to the front end, the main thread executing the request will end immediately, and the response result will be handed to another thread to return to the front end.
- This asynchrony is different from the so-called pseudo-asynchrony below, in which the main thread returns a value to the front end as soon as it completes, instead of waiting 5 seconds for the front end to return a value.
@GetMapping("call")
public String call(a) {
new Thread(new Runnable() {
@Override
public void run(a) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
return "This is a false asynchronous.";
}
Copy the code
This asynchronous ways about return Callable, have corresponding HandlerMethodReturnValueHandler implementation class, is enriched their special apis, such as what timeouts, and who is to create a thread pool to create, basic is the same process.
conclusion
- Understanding asynchronous programming of Spring MVC is beneficial to our subsequent learning of responsive programming, RXJava, WebFlux and so on.
- Asynchronous programming helps us use system resources efficiently.
The end of the
- As a result of their talent and learning, it is inevitable that there will be mistakes, if you found the wrong place, but also hope that the message to me pointed out, I will correct it.
- If you think the article is good, your forwarding, sharing, appreciation, like, message is the biggest encouragement to me.
- Thank you for reading. Welcome and thank you for your attention.
Standing on the shoulders of giants pick apples: blog.csdn.net/f641385712/…