Spring MVC的異步請求Callable

應用服務器的連接線程池實際上是有限制的;每一個連接請求都會耗掉線程池的一個連接數;如果某些耗時很長的操作,如對大量數據的查詢操作、調用外部系統提供的服務以及一些IO密集型操作等,會佔用連接很長時間,這個時候這個連接就無法被釋放而被其它請求重用。如果連接佔用過多,服務器就很可能無法及時響應每個請求;極端情況下如果將線程池中的所有連接耗盡,服務器將長時間無法向外提供服務。

1.callable方式

<code>@Controller
@RequestMapping("/async/controller")
public class AsyncHelloController {\t
\t @ResponseBody
\t @GetMapping("/hello")
\t public Callable<string> helloGet() throws Exception {
\t System.out.println(Thread.currentThread().getName() + " 主線程start");
\t Callable<string> callable = () -> {
\t System.out.println(Thread.currentThread().getName() + " 子子子線程start");
\t TimeUnit.SECONDS.sleep(5); //模擬處理業務邏輯,話費了5秒鐘
\t System.out.println(Thread.currentThread().getName() + " 子子子線程end");
\t\t\t\t// 這裡稍微小細節一下:最終返回的不是Callable對象,而是它裡面的內容
\t return "hello world";
\t };
\t System.out.println(Thread.currentThread().getName() + " 主線程end");
\t return callable;
\t }
\t}/<string>/<string>/<code>
<code>執行結果:
http-apr-8080-exec-3 主線程start
http-apr-8080-exec-3 主線程end
MvcAsync1 子子子線程start
MvcAsync1 子子子線程end/<code>
Spring MVC的異步請求Callable

異步模式處理步驟概述如下:

1.當Controller返回值是Callable的時候Spring就會將Callable交給TaskExecutor去處理(一個隔離的線程池)

2.與此同時將DispatcherServlet裡的攔截器、Filter等等都馬上退出主線程,但是response仍然保持打開的狀態Callable線程處理完成後,

3.Spring MVC講請求重新派發給容器**(注意這裡的重新派發,和後面講的攔截器密切相關)**根據Callabel返回結果,繼續處理(比如參數綁定、視圖解析等等就和之前一樣了)~~~~


分享到:


相關文章: