<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ### 返回Callable Spring MVC 3.2開始引入了基于Servlet 3的異步請求處理。相比以前,控制器方法已經不一定需要返回一個值,而是可以返回一個java.util.concurrent.Callable的對象,并通過Spring MVC所管理的線程來產生返回值 ``` @Component public class TaskService { public String execute() { try { TimeUnit.SECONDS.sleep(15); } catch (InterruptedException e) { e.printStackTrace(); } return "hello"; } } @RestController public class AsyncCallableController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final 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; } } output===> Request received Servlet thread released Slow task executed ``` Callable的異步請求被處理時所依次發生的事件: 1. 控制器先返回一個Callable對象 2. Spring MVC開始進行異步處理,并把該Callable對象提交給另一個獨立線程的執行器TaskExecutor處理 3. DispatcherServlet和所有過濾器都退出Servlet容器線程,但此時方法的響應對象仍未返回 4. Callable對象最終產生一個返回結果,此時Spring MVC會重新把請求分派回Servlet容器,恢復處理 5. DispatcherServlet再次被調用,恢復對Callable異步處理所返回結果的處理 ### 返回DeferredResult **DeferedResult處理流程** 1. Spring mvc的控制層接收用戶的請求之后,如果要采用異步處理,那么就要返回DeferedResult&lt;&gt;泛型對象。在調用完控制層之后,立即回返回DeferedResult對象,此時驅動控制層的容器主線程,可以處理更多的請求 2. 可以將DeferedResult對象作為真實響應數據的代理,而真實的數據是該對象的成員變量result,它可以是String類型,或者ModelAndView類型等 3. 容器主線程,會調用DeferedResult對象的getResult方法,然后響應到客戶端。在業務沒有處理完畢時,result真實數據還沒有形成,那么容器主線程會發生阻塞 4. 業務處理完畢之后,要執行setResult方法,將真實的響應數據賦值到DeferedResult對象中。此時,異步線程會喚醒容器主線程。那么容器主線程會繼續執行getResult方法,將真實數據響應到客戶端 ``` @RestController public class AsyncDeferredController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final TaskService taskService; @Autowired public AsyncDeferredController(TaskService taskService) { this.taskService = taskService; } @RequestMapping(value = "/deferred", method = RequestMethod.GET, produces = "text/html") public DeferredResult<String> executeSlowTask() { logger.info("Request received"); DeferredResult<String> deferredResult = new DeferredResult<>(); CompletableFuture.supplyAsync(taskService::execute) .whenCompleteAsync((result, throwable) -> deferredResult.setResult(result)); logger.info("Servlet thread released"); return deferredResult; } } ``` > 在Spring Mvc的控制層中,只要有一個用戶請求便會實例化一個DeferedResult對象,然后返回該對象,進行響應客戶端。只要DeferedResult對象不設置result響應的內容,則控制層的容器主線程在響應客戶端上就會發生阻塞。因為SpringMVC只會實例化一個Controller對象,無論有多少個用戶請求,在堆上只有一個Controller對象,因此可以添加一個成員變量List,將這些用戶請求的DeferedResult對象存放到List中,然后啟動一個定時線程掃描list,從而依次執行setResult方法,響應客戶端 ``` @Controller public class DeferedResultController { private ConcurrentLinkedDeque<DeferredResult<String>> deferredResults = new ConcurrentLinkedDeque<DeferredResult<String>>(); @RequestMapping("/getResult") @ResponseBody public DeferredResult<String> getDeferredResultController(){ //設置 5秒就會超時 final DeferredResult<String> stringDeferredResult = new DeferredResult<String>(1000); //將請求加入到隊列中 deferredResults.add(stringDeferredResult); final String message = "{username:wangbinghua}"; ExecutorService executorService = Executors.newFixedThreadPool(10); executorService.submit(new Runnable() { @Override public void run() { try { Thread.sleep(1010); } catch (InterruptedException e) { e.printStackTrace(); } //業務處理 System.out.println("業務處理"); stringDeferredResult.setResult(message); } }); //setResult完畢之后,調用該方法 stringDeferredResult.onCompletion(new Runnable() { @Override public void run() { System.out.println("異步調用完成"); //響應完畢之后,將請求從隊列中去除掉 deferredResults.remove(stringDeferredResult); } }); stringDeferredResult.onTimeout(new Runnable() { @Override public void run() { System.out.println("業務處理超時"); stringDeferredResult.setResult("error:timeOut"); } }); return stringDeferredResult; } //開啟線程定時掃描隊列,響應客戶端 @Scheduled(fixedRate = 1000) public void scheduleResult(){ System.out.println(new Date()); for(int i = 0;i < deferredResults.size();i++){ DeferredResult<String> deferredResult = deferredResults.getFirst(); deferredResult.setResult("result:" + i); } } } ``` ### DeferedResult 兩個監聽器(onCompletion & onTimeout) * 當DeferedResult對象調用setResult之后,響應完畢客戶端,則直接調用onCompletion對應的方法。 * 當業務處理相當耗時,則響應客戶端超時,也會調用onCompletion對應的方法以及onTimeout方法。此時,響應客戶端的內容為deferedResult.setErrorResult的內容,否則500錯誤。 * 發生異常,調用onCompletion方法,此時,響應客戶端的內容為deferedResult.setErrorResult的內容,否則500錯誤 ### WebAsyncTask對象使用實例 ``` @RequestMapping("/async") @ResponseBody public WebAsyncTask<String> asyncTask(){ // 1000 為超時設置 WebAsyncTask<String> webAsyncTask = new WebAsyncTask<String>(1000,new Callable<String>(){ @Override public String call() throws Exception { //業務邏輯處理 Thread.sleep(5000); String message = "username:wangbinghua"; return message; } }); webAsyncTask.onCompletion(new Runnable() { @Override public void run() { System.out.println("調用完成"); } }); webAsyncTask.onTimeout(new Callable<String>() { @Override public String call() throws Exception { System.out.println("業務處理超時"); return "<h1>Time Out</h1>"; } }); return webAsyncTask; } ``` ### 總結 Callable和Deferredresult做的是同樣的事情——釋放容器線程,在另一個線程上異步運行長時間的任務。不同的是誰管理執行任務的線程:Callable執行線程完畢即返回;Deferredresult通過設置返回對象值(deferredResult.setResult\(result\)\);)返回,可以在任何地方控制返回
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看