在springboot 正常情况下 使用 shutdown 关闭进程 是正常的,但是如果 jar包 正在运行线程任务时如果调用 shutdown 进行关闭 则会 抛出io异常并且 进程不会正常退出
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线程不存在的异常所以需要在子线程里面考虑这个场景
原文:https://www.cnblogs.com/qianxiaoPro/p/15352321.html