Spring Boot - 忽略@Async

时间:2017-04-01 21:28:54

标签: java spring multithreading asynchronous spring-boot

使用Spring Boot 1.5.2.RELEASE@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 个答案:

答案 0 :(得分:3)

您的test()函数正在调用Future实例上的get()。该函数的文档说明:“如果需要计算完成,则等待,然后检索其结果。”

因此,如果调用者可以使用ID来稍后检索结果(或切换到同步响应),那么您可能希望返回某种排序,而不是调用get()。

答案 1 :(得分:3)

你应该看一下 Future#get javadoc

  

如果需要等待计算完成,然后检索   结果。

您正在通过调用get方法将异步方法转换为同步调用。

因此,只需返回get,而不是调用Future。 Spring MVC支持future as return type

  

ListenableFuture或CompletableFuture / CompletionStage可以   当应用程序想要从a生成值时返回   线程池提交。

示例:

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