Ответ
Spring предоставляет несколько высокоуровневых абстракций для работы с многопоточностью, избавляя от необходимости напрямую управлять Thread.
1. Асинхронное выполнение через @Async:
- Требует аннотации
@EnableAsyncв конфигурации. - Метод, помеченный
@Async, выполняется в отдельном потоке. - Возвращаемый тип должен быть
void,FutureилиCompletableFuture.@Service public class NotificationService { @Async // Будет выполнен в потоке из TaskExecutor public CompletableFuture<String> sendAsync() { // Долгая операция (отправка email, запрос к API) return CompletableFuture.completedFuture("OK"); } }
2. Настройка пула потоков (TaskExecutor):
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // Основные потоки
executor.setMaxPoolSize(10); // Максимум при заполненной очереди
executor.setQueueCapacity(25); // Очередь задач
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
3. Планирование задач с @Scheduled:
- Требует
@EnableScheduling. - Для периодического или отложенного выполнения.
@Component public class ScheduledTasks { @Scheduled(fixedRate = 5000) // Каждые 5 секунд public void report() { // Логика задачи } }
4. Реактивное программирование (Spring WebFlux):
- Альтернативная модель для асинхронной неблокирующей обработки с использованием Project Reactor (
Mono,Flux).
Важные аспекты:
- Потокобезопасность: Бины по умолчанию являются синглтонами. Убедитесь, что их состояние либо неизменяемо, либо синхронизировано.
- Контекст: В асинхронных потоках теряется контекст Security, транзакций и др. Его нужно передавать явно.
- Обработка исключений: Для
@AsyncсFutureисключения оборачиваются вExecutionException. Рекомендуется использоватьAsyncUncaughtExceptionHandler.