如下內容均來自於官方文檔java
1.爲何要異步支持?web
應用服務器中的Web容器一般使用每一個客戶機請求的服務器線程。在重負載條件下,容器須要大量的線程來知足全部客戶機請求。可伸縮性限制包括耗盡內存或耗盡容器線程池。要建立可伸縮的web應用程序,您必須確保沒有與請求關聯的線程處於閒置狀態,所以容器可使用它們來處理新請求。數據庫
簡單點說,就是爲了節約服務器端的資源服務器
2.異步支持的應用場景異步
①.在構建響應以前,線程須要等待資源變爲可用或處理數據。好比,一個應用程序須要查詢數據庫或者在生成響應以前從遠程web服務訪問數據。async
②.在生成響應以前,線程須要等待一個事件。好比,一個應用程序可能必須等待一個JMS信息,在生成響應以前,等待來自另外一個客戶機的新信息或在隊列中可用的新數據。spa
這些場景表示限制web應用程序可伸縮性的操做。異步處理指將這些阻塞操做分配給一個新線程,並將與請求關聯的線程從新調整到容器線程
3.sevlet中的異步處理對象
Java EE爲servlet和過濾器提供異步處理支持。若是servlet或過濾器在處理請求時達到了潛在的阻塞操做,它能夠將操做分配給異步執行上下文,並將與請求關聯的線程當即返回到容器中,而不會生成響應。阻塞操做在不一樣線程中完成異步執行上下文,能夠生成響應或將請求發送給另外一個servlet。blog
要在servlet上啓用異步處理,能夠在@WebServlet註解上將參數asyncsupport設置爲true:
javax.servlet.AsyncContext類提供了在服務方法中執行異步處理所需的功能。要得到一個AsyncContext實例,請在服務方法的請求對象上調用startAsync()方法;例如:
此調用將請求放入異步模式,並確保在退出服務方法後不會提交響應。在阻塞操做完成或將請求發送到另外一個servlet以後,你必須在異步上下文中生成響應。
容器提供了一個不一樣的線程,其中阻塞操做能夠被處理。
AsyncContext類提供的方法:
void start(Runnable run):爲阻塞操做提供代碼,做爲實現Runnable接口的類。當調用start方法或使用其餘機制將 AsyncContext實例傳遞給類時,您能夠將該類做爲一個內部類提供。
ServletRequest getRequest():返回用於初始化此異步上下文的請求。在上面的示例中,請求與服務方法相同。
你可使用這個方法在異步上下文獲取從請求參數。
ServletResponse getResponse():返回用於初始化此異步上下文的響應。在上面的示例中,響應與服務方法相同。
你能夠在異步上下文中使用此方法來將阻塞操做的結果寫入響應。
void complete():完成異步操做並關閉與此異步上下文關聯的響應。在異步上下文中寫入響應對象以後,調用此方法。
void dispatch(String path):將請求和響應對象分派到給定的路徑。在阻塞操做完成以後,使用此方法讓另外一個servlet寫入響應。
4.實例
MyRemoteResource是一個模擬的資源類。
解釋:
在上面的列子中,startasync()使請求被異步處理;在服務方法結束時,不會將響應發送到客戶端。acontext.start(new Runnable(){})從容器中獲取一個新線程。
內部類的run()方法中的代碼在新線程中執行。內部類能夠訪問異步上下文,從請求中讀取參數並寫入響應。調用異步上下文的complete()方法提交響應並將其發送給客戶機。
AsyncServlet的服務方法當即返回,請求在異步上下文中處理。