简体   繁体   中英

Spring Boot - @Async is ignored

Using Spring Boot 1.5.2.RELEASE and the @Async annotation seems to be ignored.

Have setup the environment like this:

@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;
    }

    ...

... the async method itself:

@Service
public class MyService {

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

        Long test = 1023L;

        Thread.sleep(10000);

        return new AsyncResult<>(test);
    }
}

... now I'm trying to use this:

@RestController
public MyController {

    @Autowired
    public MyService myService;

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

... and the controller method still hangs for 10sec instead of to be immediatelly returned.

The @Async method is called from the different object. It's neither private nor transactional one as it mentioned at the similar questions.

How to let the method to be invoked asynchronously?

Your test() function is invoking get() on the Future instance. The documentation for this function states: "Waits if necessary for the computation to complete, and then retrieves its result."

So rather than invoking get(), you likely want to return some sort if ID that the caller can use to retrieve the result at a later time (or switch to a synchronous response).

You should have a look at the Future#get javadoc :

Waits if necessary for the computation to complete, and then retrieves its result.

You are transforming your async method to a synchronous call by calling get method.

Thus instead of calling get , just return the Future . Spring MVC supports future as return type :

A ListenableFuture or CompletableFuture/CompletionStage can be returned when the application wants to produce the value from a thread pool submission.

Example:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM