Introduction

Allows operations (I/O, external API calls, email sending, batch processing, ...) to run separately from the main request thread, improving:


SpringBoot

application.yaml

spring:
	task:
		execution:
			pool:
				core-size: 10
				max-size=: 50
				queue-capacity: 200
			thread-name-prefix: my-async-

Common Approaches in Spring Boot

  1. @Async

    @Service
    public class AsyncService {
    
        @Async("taskExecutor")
        public CompletableFuture<String> asyncTask(String name) {
            try {
                Thread.sleep(2000); // simulate delay
            } catch (InterruptedException ignored) {}
    
            return CompletableFuture.completedFuture("hello " + name);
        }
    
        @Async("taskExecutor")
        public void asyncVoidTask() {
            throw new RuntimeException("oops");
        }
    }
    

    Usage:

    @RestController
    public class TestController {
    
        private final AsyncService asyncService;
    
        public TestController(AsyncService asyncService) {
            this.asyncService = asyncService;
        }
    
        @GetMapping("/test")
        public String test() throws Exception {
            CompletableFuture<String> future =
                    asyncService.asyncTask("world");
    
            String result = future.get(3, TimeUnit.SECONDS); // careful: blocking
            return "result: " + result;
        }
    }
    
  2. CompletableFuture / Future / ListenableFuture

  3. Reactor (Mono/Flux) / WebFlux

    Mono.fromCallable(() -> blockingCall())
        .subscribeOn(Schedulers.boundedElastic())
        .map(result -> ...)