2017-12-26 38 views
0

一度生成されたスレッドを持つスプリングブートスレッドプールプロジェクトを作成しましたが、メンテナンスのためにサーバーでアプリケーションを停止する必要があるとき現在のタスクを完了した後にシャットダウンし、新しいタスクを実行しません。24時間365日実行中のSpringブートスレッドプールプロジェクトを友好的にシャットダウンする

同じのための私のコードは次のとおりです。 Configクラス

@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; 
} 

} 

メインクラス:私は停止する必要がある場合は理解して助けを必要と

@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)oth whileループと終了で現在のループを完了した後にerwiseします。

答えて

0

私はあなたのPOC processCommandでのThread.sleepを呼び出すで以来、問題

1)を解決するために、このコードの変更のカップルを提案するときにシャットダウンエグゼキュータ、それが呼び出されますInterruptedExceptionある労働者を中断したが、ほとんどでは無視されますあなたのコード。その後、(Thread.currentThread().InInrupted())チェックが上記の理由でfalseを返すかどうかを確認します。同様の問題は、次のコードの変更が問題解決すべき

how does thread.interrupt() sets the flag?

下のポストに概説されている:

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

2)もあるためThreadConfigのを::のTaskExecutor executorPool.setWaitForTasksToCompleteOnShutdown(真の)春の意志executor.shutdownNowの代わりにexecutor.shutdownを呼び出します。 javadoc ExecutorService.shutdownによると

は以前に提出したタスクが を実行される通常のシャットダウンを開始しますが、新しいタスクは受け入れられません。

だから私はこのコードで改善することが

executorPool.setWaitForTasksToCompleteOnShutdown(false); 

他のものを設定することをお勧めします:データ移行がコンポーネントとして注釈を付けているが、このクラスのインスタンスは、春ではないcrearedされています。 SpringがDataMigrationのインスタンスを開始させるために、ThreadConfig :: taskExecutorに似たファクトリメソッドを使用して、他のBeanをDataMigrationインスタンスに挿入するようにしてください。シャットダウンエグゼキュータするためには

あなたが例えばアクチュエータモジュールを追加し、シャットダウンエンドポイント有効にすることができ Linux環境でのjarファイルを実行している:

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

application.properties中:

endpoints.shutdown.enabled=true 

それをJMXのシャットダウンエンドポイントが有効になり、シャットダウンを呼び出すことができます。 タスクの現在のジョブサイクルが終了したい場合は、リモートで使用すると、RMIレジストリのポートを指定する必要があり、LinuxのenvをであなたのJVMプロセスに接続するためには

executorPool.setWaitForTasksToCompleteOnShutdown(true); 

を設定する必要があります。ここ は、詳細な記事です: How to access Spring-boot JMX remotely

あなただけのローカルENVからJMXに接続する必要がある場合は、jsoncole実行するか、またはコマンドラインツールすることができます:ここで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

ありがとうございます。しかし、もう一つ理解する必要があります。私はこの春のブートの瓶を作り、Linux環境で動かします。どうすればこのプロセスを止めることができますか?私はそれを24時間365日稼働するように設計し、何らかのタスクを実行する必要があるため、スプリングブートを停止しようとすると、新しいwhileループを開始する前に現在の実行タスクを完了して停止する必要があります。コードデザインで私を助けてください。ありがとう –

+0

答えを明確にしました。それが助けてくれることを願って –

+0

ありがとう。返信のために!そして、アプリケーションをシャットダウンするためにlinux envのJMX終了エンドポイントを呼び出す方法。 –