@Scheduled с fixedRate — задачи наслаиваются друг на друга

@Scheduled(fixedRate = 5000) запускает следующий вызов через 5 секунд после старта предыдущего, независимо от того, закончился он или нет. Если задача обычно выполняется 2 секунды, а один раз — из-за лока в БД или медленного внешнего вызова — 20 секунд, следующие запуски не отменяются, они копятся в очереди планировщика.

По умолчанию Spring использует однопоточный TaskScheduler с пулом размера 1. Значит, накопленные вызовы не выполняются параллельно — они выстраиваются в очередь и срабатывают подряд, один за другим, как только предыдущий закончился. Со стороны это выглядит как сервис, который внезапно начинает бомбить внешний API или БД пачкой запросов.

fixedDelay отличается тем, что отсчитывает интервал от завершения предыдущего запуска, а не от его старта — при долгой задаче наложения не будет вообще, просто следующий запуск сдвинется по времени.

@Scheduled(fixedDelay = 5000) public void syncOrders() { // следующий запуск через 5 сек // после завершения этого метода }

На собеседовании часто спрашивают не про сам fixedRate, а про то, что происходит, если задача виснет надолго — например, ждёт лок на строке в Postgres. Правильный ответ включает и настройку пула scheduler'а: если он однопоточный, зависшая задача блокирует не только свои повторы, но и все остальные @Scheduled методы в приложении, если они используют тот же дефолтный TaskScheduler.

fixedRate считает от старта, fixedDelay — от завершения. Для задач с непредсказуемой длительностью fixedDelay безопаснее почти всегда.

Тренажёр: 600 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки