2017-04-01 55 views
0

使用Spring Boot 1.5.2.RELEASE@Async註釋似乎被忽略。Spring Boot - @Async被忽略

已經設置這樣的環境:

@SpringBootApplication 
@EnableAsync 
public class Application extends AsyncConfigurerSupport { 

    public static void main(String[] args) { 
     SpringApplication.run(Application.class, args); 
    } 

    @Override 
    public Executor getAsyncExecutor() { 

     ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 

     executor.setCorePoolSize(2); 
     executor.setMaxPoolSize(2); 
     executor.setQueueCapacity(500); 
     executor.setThreadNamePrefix("async-task-"); 

     executor.initialize(); 

     return executor; 
    } 

    ... 

...異步方法本身:

@Service 
public class MyService { 

    @Async 
    public Future<Long> asyncTask() throws Exception { 

     Long test = 1023L; 

     Thread.sleep(10000); 

     return new AsyncResult<>(test); 
    } 
} 

...現在我想要使用此:

@RestController 
public MyController { 

    @Autowired 
    public MyService myService; 

    @PostMapping("/test") 
    public ResponseEntity<MyResponse> test() { 
     return new ResponseEntity<>(
         new MyResponse(myService 
          .asyncTask() 
          .get()), 
         HttpStatus.OK); 
    } 
} 

...和控制器方法仍然掛起10sec,而不是立即返回。

從不同的對象調用@Async方法。它既不是私有的也不是交易型的,就像它在類似問題中提到的一樣。

如何讓該方法異步調用?

+2

它*是*被異步調用。然後你的控制器明確阻止響應。 – chrylis

+5

這個。當您調用get()時,您正在等待任務完成,以便您可以檢索結果。 –

+1

我強烈建議您閱讀Spring MVC –

回答

2

您的test()函數正在Future實例上調用get()。該函數的文檔聲明:「如果需要,等待計算完成,然後檢索其結果。」

因此,如果調用者以後可能用來檢索結果的ID(或切換到同步響應),您可能希望返回某種排序而不是調用get()。

2

你應該看看 Future#get javadoc

如有必要,等待計算完成,然後檢索 其結果。

您正在通過調用get方法將異步方法轉換爲同步調用。

因此,不要致電get,只需返回Future。 Spring MVC的支持future as return type

一個ListenableFuture或CompletableFuture/CompletionStage可以 被當應用程序要生產從 線程池提交返回的值。

實施例:

return myService.asyncTask().thenApply(r -> ResponseEntity.ok(new MyResponse(r))); 
+0

有趣的評論,謝謝 – WildDev