springboot通过shutdown进程依然存活的问题

问题描述:

在springboot 正常情况下 使用 shutdown 关闭进程 是正常的,但是如果 jar包 正在运行线程任务时如果调用 shutdown 进行关闭 则会 抛出io异常并且 进程不会正常退出

解决方法:

创建ShutdownAction类

package com.ecolor.energy.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * <p>Created with IntelliJ IDEA.、</p>
 * <p>Computer: Administrator、</p>
 * <p>Author:QiaXiao19、</p>
 * <p>Date: 2021/9/26 0026 周日 09:14</p>
 * <p>Project:energy</p>
 * <p>Description: No Description</p>
 */
@Slf4j
public class ShutdownAction implements ApplicationListener<ContextClosedEvent> {
    private ClassWithExecutor classWithExecutor;

    public ShutdownAction(ClassWithExecutor classWithExecutor) {
        this.classWithExecutor = classWithExecutor;
    }
    @Override
    public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
        classWithExecutor.shutdown();
    }

    public static class ClassWithExecutor {
        ScheduledExecutorService es;

        public ClassWithExecutor() {
            this.es = Executors.newSingleThreadScheduledExecutor();
        }

        public void startScheduledTask() {
            es.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
//                    System.out.println("Printing this every minute");
                }
            }, 0, 3, TimeUnit.SECONDS);
        }

        public void shutdown() {
            // 有序关闭现在的线程
            es.shutdown();
            try {
                // 判断当前是否还有没有关闭的线程,超时时间60秒。
                boolean b = es.awaitTermination(60, TimeUnit.SECONDS);
                if (!b){
                    // 超时时 强制关闭线程池中所有的现成
                    log.error("this is stop All task");
                    es.shutdownNow();
                }
            } catch (InterruptedException e) {
                log.error("this is stop All task");
//                e.printStackTrace();
                es.shutdownNow();
            }
        }
    }
}

在启动文件处注入以上的类

package com.ecolor.energy;

import com.ecolor.energy.config.ShutdownAction;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;

import javax.annotation.PostConstruct;

@SpringBootApplication
// 开启定时任务
@EnableScheduling
public class EnergyApplication {
    public static void main(String[] args) {
        SpringApplication.run(EnergyApplication.class, args);
    }
    @Bean
    public ShutdownAction.ClassWithExecutor ce() {
        return new ShutdownAction.ClassWithExecutor();
    }

    @Bean
    ShutdownAction sa() {
        return new ShutdownAction(ce());
    }

    @PostConstruct
    public void startScheduledTask() {
        ce().startScheduledTask();
    }
}

结语:

.如果存在定时任务之类的子线程正在执行查询数据库等操作时有可能会出现 先关闭了jdbc的线程然后 子线程会抛出 jdbc线程不存在的异常所以需要在子线程里面考虑这个场景

posted @ 2021-09-29 12:32  浅笑19  阅读(705)  评论(0编辑  收藏  举报