"Turn" to understand callable and Spring Deferredresult

Source: Internet
Author: User

Http://www.cnblogs.com/aheizi/p/5659030.html 1-Introduction

Asynchronous support in Servlet 3 provides the possibility of processing HTTP requests in another thread. This is particularly interesting when there is a long-running task, because when another thread processes the request, the container thread is freed and can continue to serve other requests.
This topic has been explained many times, and the classes provided by the Spring framework for this feature seem a bit confusing-returning callable and Deferredresult in a controller.
In this article, I will implement these two examples to show the differences.
All examples shown here include executing a controller that will perform a long-running task and then return the results to the client. Long-running tasks are handled by Taskservice:

@ServicePublicclass taskserviceimpl implements Span class= "Hljs-title" >taskservice {private final Logger Logger = Loggerfactory.getlogger (this.getclass ());  @Override public String execute () {try {thread.sleep (5000); Logger.info ( "Slow task executed"); return  "Task finished";} catch (interruptedexception e) {throw new runtimeexception ();} }} 

This web application was created with spring boot, and we will execute the following class to run our example:

@SpringBootApplicationpublic class MainApp { public static void main(String[] args) { SpringApplication.run(MainApp.class, args); }}
2-Blocked Controller

In this example, a request arrives at the controller. The servlet thread is not freed until a long-running method is executed and we exit @requestmapping the comment method.

@RestControllerPublicClassBlockingcontroller {PrivateFinal Logger Logger = Loggerfactory.getlogger (This.getclass ());private final taskservice taskservice;  @Autowired public blockingcontroller (Taskservice taskservice) { This.taskservice = Taskservice; }  @RequestMapping (value =  "/block", method = Requestmethod.get, produces =  "text/html") public String executeslowtask () {Logger.info (  "Request received"); String result = Taskservice.execute (); Logger.info ( "Servlet thread released"); return result;}}            

If we run this example Http://localhost:8080/block, in the log we will find that the servlet request will not be released until the long task is finished (5 seconds later).

2015-07-12 12: 41: 11.849[Nio-8080-exec-6]X. s. Web. controller. Blockingcontroller:Requestreceived2015-07-12 12: 41: 16.851[Nio-8080-exec-6]x. Spring. Web. Service. Taskserviceimpl: Slow task executed2015-07-12::16.851 [nio-8080-exec-6] x . s. Web. Controller. Blockingcontroller: Servlet thread released         
3-Return callable

In this example, instead of returning the result directly, we will return a callable:

@RestControllerPublicClassAsynccallablecontroller {PrivateFinal Logger Logger = Loggerfactory.getlogger (This.getclass ());Privatefinal taskservice taskservice;  @Autowired public asynccallablecontroller (Taskservice Taskservice) { this.taskservice = Taskservice;}  @RequestMapping (value =  "/callable", method = Requestmethod.get, produces =  "text/html") public callable<string> executeslowtask () {Logger.info ( "Request received"); callable<string> callable = Taskservice::execute; Logger.info ( "Servlet thread released"); return callable;}           

Returning callable means that spring MVC will invoke a task that performs the definition in a different thread. Spring will use Taskexecutor to manage threads. The servlet thread will be freed before waiting for a long-term task to complete.

2015-07-12 13: 07: 07.012[Nio-8080-exec-5]X. s. W. C. Asynccallablecontroller:Requestreceived2015-07-12 13: 07: 07.013[Nio-8080-exec-5]x.s.w.cservlet thread released2015-07-12 13 :07:12.014 [MvcAsync2] x .spring.web .serviceslow task executed            

You can see that we have returned from the servlet before the long-running task has finished executing. This does not mean that the client has received a response. Communication with the client is still an open waiting result, but the received request for the thread has been freed and can serve the request of another customer.

4-Return Deferredresult

First, we need to create a Deferredresult object. This object will be returned by the controller. We will complete and callable the same thing when we release the servlet thread while another thread is working on a long-running task.

@RestControllerPublicClassAsyncdeferredcontroller {PrivateFinal Logger Logger = Loggerfactory.getlogger (This.getclass ());PrivateFinal Taskservice Taskservice;@AutowiredPublicasyncdeferredcontroller (Taskservice TaskService) {this.taskservice = Taskservice; }  @RequestMapping (value =  "/deferred", method = Requestmethod.get, produces =  "text/html") public deferredresult<string> executeslowtask () {Logger.info ( Span class= "hljs-string" > "Request received"); deferredresult<string> Deferredresult = new deferredresult<> (); Completablefuture.supplyasync (Taskservice::execute). Whencompleteasync ((result, throwable) Deferredresult.setresult (result)); Logger.info ( "Servlet thread released"); return Deferredresult;}           

So, what's the difference between returning Deferredresult and returning to callable? The difference is that this time the thread is managed by us. It is up to us to create a thread and set the result to Deferredresult.
Create an asynchronous task with Completablefuture. This will create a new thread where our long running tasks will be executed. That is, in this thread, we will set the result to Deferredresult and return.
In which thread pool are we retrieving this new thread? By default, the Supplyasync method in Completablefuture will run the task in the Forkjoin pool. If you want to use a different thread pool, you can pass a executor to the Supplyasync method:

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

If we run this example, we will get the following result:

2015-07-12 13: 28: 08.433[IO-8080-EXEC-10]X. s. W. C. Asyncdeferredcontroller:Requestreceived2015-07-12 13: 28: 08.475[IO-8080-EXEC-10]x. s. W. C. Asyncdeferredcontroller: Servlet thread released2015-07-12:13.469 [ ONPOOL-WORKER-1] x. Spring. Web. Service. Taskserviceimpl: Slow task executed          
5-Conclusion

Standing at a certain altitude, callable and deferredresult do the same thing-releasing the container thread and running the long task asynchronously on another thread. The difference is who manages the threads that perform the task.

The code involved in this article spring-rest

"Turn" to understand callable and Spring Deferredresult

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.