2017-12-26 38 views
0

한 번 생성 된 스레드가 24x7 실행해야하는 스레드가있는 스프링 부트 스레드 풀 프로젝트를 만들었지 만 유지 관리를 위해 서버에서 응용 프로그램을 중지해야 할 때 현재 작업을 완료 한 후 종료하고 새 작업을 다시 시작하지 않습니다.24x7 실행중인 스프링 부트 스레드 풀 프로젝트를 우회적으로 종료 할 수 있습니다

동일한에 대한 나의 코드는 다음과 같습니다 구성 클래스

@Configuration 
public class ThreadConfig { 
    @Bean 
    public ThreadPoolTaskExecutor taskExecutor(){ 
    ThreadPoolTaskExecutor executorPool = new ThreadPoolTaskExecutor(); 
    executorPool.setCorePoolSize(10); 
    executorPool.setMaxPoolSize(20); 
    executorPool.setQueueCapacity(10); 
    executorPool.setWaitForTasksToCompleteOnShutdown(true); 
    executorPool.setAwaitTerminationSeconds(60); 
    executorPool.initialize(); 

    return executorPool; 
} 
} 

의 Runnable 클래스

@Component 
@Scope("prototype") 
public class DataMigration implements Runnable { 

String name; 

private boolean run=true; 

public DataMigration(String name) { 
    this.name = name; 
} 

@Override 
public void run() { 
    while(run){ 

    System.out.println(Thread.currentThread().getName()+" Start Thread = "+name); 
    processCommand(); 
    System.out.println(Thread.currentThread().getName()+" End Thread = "+name); 
    if(Thread.currentThread().isInterrupted()){ 
     System.out.println("Thread Is Interrupted"); 
     break; 
    } 

    } 
} 

private void processCommand() { 
    try { 
     Thread.sleep(5000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

public void shutdown(){ 
    this.run = false; 
} 

} 

Main 클래스 : 나는 중지해야 할 경우 이해하는 데 도움이 필요

@SpringBootApplication 
public class DataMigrationPocApplication implements CommandLineRunner{ 

@Autowired 
private ThreadPoolTaskExecutor taskExecutor; 

public static void main(String[] args) { 
    SpringApplication.run(DataMigrationPocApplication.class, args); 
} 

@Override 
public void run(String... arg0) throws Exception { 

    for(int i = 1; i<=20 ; i++){ 
     taskExecutor.execute(new DataMigration("Task " + i)); 
    } 

    for (;;) { 
     int count = taskExecutor.getActiveCount(); 
     System.out.println("Active Threads : " + count); 
     try { 
      Thread.sleep(10000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     if (count == 0) { 
      taskExecutor.shutdown(); 
      break; 
     } 

    } 
    System.out.println("Finished all threads"); 

} 
} 

내 스프링 부팅 응용 프로그램은 실행중인 모든 20 개의 스레드를 중지해야합니다 (24x7) while 루프 및 종료에서 현재 루프를 완료 한 후 erwise.

답변

0

나는 당신의 POC processCommand가에 Thread.sleep 호출에 이후 문제

1)를 해결하려면이 코드에서 변경의 몇 가지를 제안 할 때 종료 집행자 그것은 호출되는 예외 : InterruptedException 노동자를 중단하지만 거의 무시됩니다 당신의 코드. 그 후 (Thread.currentThread(). isInterrupted()) 검사가 위의 이유로 false를 반환하는지 확인합니다. 비슷한 문제가 문제를 해결해야

how does thread.interrupt() sets the flag?

다음 코드 변경 아래의 게시물에 설명되어 있습니다 : 때문에의 threadconfig의도)

private void processCommand() { 
    try { 
     Thread.sleep(5000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
     shutdown(); 
    } 
} 

2 :: 된 TaskExecutor executorPool.setWaitForTasksToCompleteOnShutdown을 (참) 봄 것 executor.shutdownNow 대신 executor.shutdown을 호출하십시오. javadoc ExecutorService.shutdown에 따르면

은 이전에 제출 한 작업을 실행 을하는 순서대로 종료를 시작하지만, 새로운 작업이 허용되지 않습니다.

그래서 나는이 코드를 개선하기 위해

executorPool.setWaitForTasksToCompleteOnShutdown(false); 

다른 일을 설정하는 것이 좋습니다 : DataMigration이 구성 요소로 주석이 있지만,이 클래스의 인스턴스는 봄으로하지 creared된다. Spring이 DataMigration의 인스턴스를 초기화 (예 : 다른 Bean을 DataMigration 인스턴스에 삽입)하도록하려면 ThreadConfig :: taskExecutor와 유사한 팩토리 메소드를 사용해야합니다. 종료 집행하기 위해

당신은 예를 들어 액츄에이터 모듈을 추가 및 종료 엔드 포인트 활성화 할 수 있습니다 리눅스 환경에서 jar 파일을 실행 :

<dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-actuator</artifactId> 
</dependency> 

application.properties에서 :

endpoints.shutdown.enabled=true 

그것을 JMX 종료점을 사용할 수있게되고 종료점을 호출 할 수 있습니다. 작업을 완료 할 작업의 현재 작업주기를 원하는 경우 원격 당신은 RMI 레지스트리 포트를 지정해야합니다 리눅스 ENV에 JVM 프로세스에 연결하기 위해

executorPool.setWaitForTasksToCompleteOnShutdown(true); 

을 설정해야합니다. 여기 상세한 기사입니다 : How to access Spring-boot JMX remotely

당신은 당신이 jsoncole 또는 명령 행 도구를 실행할 수있는 지역 ENV에서 JMX에 연결해야하는 경우 : 여기

Calling JMX MBean method from a shell script 이러한 도구 중 하나를 사용하여 예제 UF입니다 - jmxterm

$>run -d org.springframework.boot: -b  org.springframework.boot:name=shutdownEndpoint,type=Endpoint shutdown 
#calling operation shutdown of mbean org.springframework.boot:name=shutdownEndpoint,type=Endpoint with params [] 
#operation returns: 
{ 
    message = Shutting down, bye...; 
} 
+0

제안 해 주셔서 감사합니다. 하지만 한 가지 더 이해해야합니다. 저는이 봄 부팅의 항아리를 만들고 리눅스 환경에서 실행합니다. 이 과정을 어떻게 중단 할 것입니까? 24x7로 실행되도록 설계하고 작업을 수행해야하기 때문에 스프링 부트를 중지하려고하면 현재 실행중인 작업을 완료하고 새로운 while 루프를 시작하기 전에 중지해야합니다. 코드 디자인을 도와주세요. 감사합니다 –

+0

대답을 명확히했습니다. 도움이 되었으면 좋겠다 –

+0

고마워. 답장! 그리고 응용 프로그램을 종료하기 위해 linux env에서 JMX 종료 종점을 호출하는 방법. –