如何友好地关闭Spring引导线程池项目,这是24x7运行

问题描述 投票:0回答:1

我创建了一个spring boot thread pool项目,它有一个需要在生成后24x7运行的线程,但是当我需要在服务器中停止应用程序进行一些维护时,它应该在完成当前任务后关闭,而不是接受任何新任务。

我的代码是: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");

}
}

我需要帮助才能理解我是否需要停止我的spring启动应用程序它应该停止运行的所有20个线程运行(24x7),否则在完成while循环和退出时的当前循环之后。

spring multithreading spring-boot pool
1个回答
0
投票

我会在此代码中提出一些更改来解决问题

1)因为在你的POC processCommand调用Thread.sleep,当你关闭执行程序并且它中断了工作程序InterruptedException被调用但在你的代码中几乎被忽略。之后有if(Thread.currentThread()。isInterrupted())检查哪个将返回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(true)Spring将调用executor.shutdown而不是executor.shutdownNow。根据javadoc ExecutorService.shutdown

启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务。

所以我建议设置

executorPool.setWaitForTasksToCompleteOnShutdown(false);

在这段代码中需要改进的其他事项:虽然DataMigration被注释为一个组件,但是这个类的实例不是由Spring创建的。您应该尝试使用类似于ThreadConfig :: taskExecutor的工厂方法,以使Spring启动DataMigration实例,例如将其他bean注入DataMigration实例。

为了在linux环境下运行jar文件时关闭执行程序,您可以添加执行器模块并启用关闭端点:

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

在application.properties中:

endpoints.shutdown.enabled=true

它将启用JMX关闭端点,您可以在其上调用shutdown。如果您想要完成任务的当前作业周期,您应该设置

executorPool.setWaitForTasksToCompleteOnShutdown(true);

为了远程连接到linux env上的jvm进程,你必须指定一个RMI注册表端口。这是一篇详细的文章:How to access Spring-boot JMX remotely

如果您只需要从本地环境连接到JMX,您可以运行jsoncole或命令行工具:Calling JMX MBean method from a shell script

以下是使用这些工具之一的示例 - 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...;
}
© www.soinside.com 2019 - 2024. All rights reserved.