Жизненный цикл serviceLoader выглядит странно — он инициализируется прямо во время выполнения метода или службы, затем назначает некоторую работу, а затем служба возвращается. Что происходит со ссылкой на этот пул? когда отключение может быть вызвано?
Кроме того, первая итерация запускается сразу, и это происходит, когда контекст приложения еще не готов, это может привести к непредсказуемым результатам в зависимости от фактического кода, который выполняется во время итерации.
Я не могу точно сказать, что происходит на основе этого фрагмента кода, но вот несколько возможных решений:
Используйте аннотацию @Scheduled
, запуск запланированных задач — это встроенная функция Spring. Учебников много, вот один из них
Если вам абсолютно необходимо использовать пул потоков, я предлагаю следующую конфигурацию:
@Configuration
public class MyConfiguration {
@Bean
public Service service() {
return new Service();
}
@Bean(destroyMethod="shutdownNow") // or shutdown - now spring will close the pool when the app context gets closed
@Qualifier("serviceLoaderPool")
public ScheduledExecutorService serviceLoader() {
return Executors.newScheduledThreadPool(1);
}
@EventListener
public void onAppContextStarted(ApplicationReadyEvent evt) {
ScheduledExecutorService loader =
(ScheduledExecutorService)evt.getApplicationContext().getBean("serviceLoaderPool");
Service service = evt.getApplicationContext.getBean(Service.class);
loader.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
service.loadAllLiveEvents();
}
}, 0, 1, TimeUnit.HOURS);
}
}
При таком подходе вы можете быть уверены, что служба начнет обновляться, когда контекст приложения будет готов.
Жизненный цикл службы-исполнителя также четко определен, Spring управляет им как обычным одноэлементным компонентом, поэтому он не будет подвергаться сборке мусора, пока контекст приложения запущен.
Наличие метода destroy гарантирует корректное завершение работы (опять же, Spring вызовет его за вас).
person
Mark Bramnik
schedule
19.02.2020