복붙노트

[SPRING] Spring Boot - 배포시 백그라운드 스레드를 시작하는 가장 좋은 방법

SPRING

Spring Boot - 배포시 백그라운드 스레드를 시작하는 가장 좋은 방법

Tomcat 8에 스프링 부트 응용 프로그램을 배포했습니다. 응용 프로그램이 시작되면 Spring Autowires에서 종속성이있는 백그라운드에서 작업자 스레드를 시작하고 싶습니다. 현재 나는 이것을 가지고있다 :

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan
public class MyServer extends SpringBootServletInitializer {   

    public static void main(String[] args) {
        log.info("Starting application");
        ApplicationContext ctx = SpringApplication.run(MyServer.class, args);
        Thread subscriber = new Thread(ctx.getBean(EventSubscriber.class));
        log.info("Starting Subscriber Thread");
        subscriber.start();
    }

내 Docker 테스트 환경에서는 정상적으로 작동하지만 Tomcat 8의 Linux (Debian Jessie, Java 8) 호스트에 배포하면 "Starting Subscriber Thread"메시지가 표시되지 않고 스레드가 시작되지 않습니다.

해결법

  1. ==============================

    1.응용 프로그램을 비 임베디드 응용 프로그램 서버에 배포 할 때 main 메서드가 호출되지 않습니다. 스레드를 시작하는 가장 간단한 방법은 beans 생성자에서 수행하는 것입니다. 또한 컨텍스트가 닫힐 때 스레드를 정리하는 것이 좋습니다. 예를 들면 다음과 같습니다.

    응용 프로그램을 비 임베디드 응용 프로그램 서버에 배포 할 때 main 메서드가 호출되지 않습니다. 스레드를 시작하는 가장 간단한 방법은 beans 생성자에서 수행하는 것입니다. 또한 컨텍스트가 닫힐 때 스레드를 정리하는 것이 좋습니다. 예를 들면 다음과 같습니다.

    @Component
    class EventSubscriber implements DisposableBean, Runnable {
    
        private Thread thread;
        private volatile boolean someCondition;
    
        EventSubscriber(){
            this.thread = new Thread(this);
            this.thread.start();
        }
    
        @Override
        public void run(){
            while(someCondition){
                doStuff();
            }
        }
    
        @Override
        public void destroy(){
            someCondition = false;
        }
    
    }
    
  2. ==============================

    2.ApplicationListener onApplicationEvent는 이미 시작되지 않은 상태에서 스레드를 시작하기 만하면 호출됩니다. 그런데 ApplicationReadyEvent를 원한다고 생각합니다.

    ApplicationListener onApplicationEvent는 이미 시작되지 않은 상태에서 스레드를 시작하기 만하면 호출됩니다. 그런데 ApplicationReadyEvent를 원한다고 생각합니다.

    편집하다 응용 프로그램 컨텍스트 초기화 이벤트에 후크를 추가하는 방법은 무엇입니까?

    @Component
    public class FooBar implements ApplicationListener<ContextRefreshedEvent> {
    
        Thread t = new Thread();
    
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            if (!t.isAlive()) {
                t.start();
            }
        }
    }
    
  3. from https://stackoverflow.com/questions/39737013/spring-boot-best-way-to-start-a-background-thread-on-deployment by cc-by-sa and MIT license