@Async chạy method trong thread pool riêng — non-blocking từ phía caller.
java
@SpringBootApplication @EnableAsync
class App {}
@Service
class EmailService {
@Async
public CompletableFuture<Void> sendWelcome(String email) {
mailSender.send(email);
return CompletableFuture.completedFuture(null);
}
}
// caller: emailService.sendWelcome(email); // fire-and-forget, return ngayThread pool config (quan trọng):
java
@Bean TaskExecutor taskExecutor() {
var exec = new ThreadPoolTaskExecutor();
exec.setCorePoolSize(5); exec.setMaxPoolSize(20); exec.setQueueCapacity(100);
exec.initialize(); return exec;
}Không có custom executor: Spring dùng SimpleAsyncTaskExecutor (tạo thread mới mỗi task, không pool → OOM khi tải cao). Bẫy giống @Transactional: this.method() bypass proxy → không async; gọi qua bean khác.