refactor: 应用关闭,关闭自定义线程池ScheduledExecutorService

* 程序结束,关闭ScheduledExecutorService 线程池。
This commit is contained in:
jasmine
2024-04-15 03:34:56 +00:00
committed by Charles7c
parent dbb7a6319e
commit c4051a6465
2 changed files with 94 additions and 0 deletions

View File

@@ -20,6 +20,7 @@ import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -30,9 +31,13 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import top.continew.starter.core.constant.PropertiesConstants;
import top.continew.starter.core.util.ExceptionUtils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 线程池自动配置
@@ -69,6 +74,11 @@ public class ThreadPoolAutoConfiguration {
executor.setKeepAliveSeconds(properties.getKeepAliveSeconds());
// 配置当池内线程数已达到上限的时候,该如何处理新任务:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 关闭线程池是否等待任务完成
executor.setWaitForTasksToCompleteOnShutdown(properties.isWaitForTasksToCompleteOnShutdown());
// 执行器在关闭时阻塞的最长毫秒数,以等待剩余任务完成执行。
executor.setAwaitTerminationMillis(properties.getAwaitTerminationMillis());
log.debug("[ContiNew Starter] - Auto Configuration 'ThreadPoolTaskExecutor' completed initialization.");
return executor;
}
@@ -88,7 +98,65 @@ public class ThreadPoolAutoConfiguration {
ExceptionUtils.printException(runnable, throwable);
}
};
// 应用关闭时,关闭线程池
SpringApplication.getShutdownHandlers().add(() -> {
shutdown(executor, properties);
});
log.debug("[ContiNew Starter] - Auto Configuration 'ScheduledExecutorService' completed initialization.");
return executor;
}
/**
* 根据相应的配置设置关闭 ExecutorService
*
* @see org.springframework.scheduling.concurrent.ExecutorConfigurationSupport#shutdown()
*/
public void shutdown(ExecutorService executor, ThreadPoolProperties properties) {
log.debug("[ContiNew Starter] - Shutting down ScheduledExecutorService start.");
if (executor != null) {
if (properties.isWaitForTasksToCompleteOnShutdown()) {
executor.shutdown();
} else {
for (Runnable remainingTask : executor.shutdownNow()) {
cancelRemainingTask(remainingTask);
}
}
awaitTerminationIfNecessary(executor, properties);
log.debug("[ContiNew Starter] - Shutting down ScheduledExecutorService complete.");
}
}
/**
* Cancel the given remaining task which never commenced execution,
* as returned from {@link ExecutorService#shutdownNow()}.
*
* @param task the task to cancel (typically a {@link RunnableFuture})
* @see RunnableFuture#cancel(boolean)
* @since 5.0.5
*/
protected void cancelRemainingTask(Runnable task) {
if (task instanceof Future<?> future) {
future.cancel(true);
}
}
/**
* Wait for the executor to terminate, according to the value of the properties
*/
private void awaitTerminationIfNecessary(ExecutorService executor, ThreadPoolProperties properties) {
if (properties.getAwaitTerminationMillis() > 0) {
try {
if (!executor.awaitTermination(properties.getAwaitTerminationMillis(), TimeUnit.MILLISECONDS)) {
if (log.isWarnEnabled()) {
log.warn("[ContiNew Starter] - Timed out while waiting for executor 'ScheduledExecutorService' to terminate.");
}
}
} catch (InterruptedException ex) {
if (log.isWarnEnabled()) {
log.warn("[ContiNew Starter] - Interrupted while waiting for executor 'ScheduledExecutorService' to terminate");
}
Thread.currentThread().interrupt();
}
}
}
}

View File

@@ -54,6 +54,16 @@ public class ThreadPoolProperties {
*/
private int keepAliveSeconds = 300;
/**
* 关闭线程池是否等待任务完成
*/
private boolean waitForTasksToCompleteOnShutdown = false;
/**
* 执行器在关闭时阻塞的最长毫秒数,以等待剩余任务完成执行。
*/
private long awaitTerminationMillis = 0;
public boolean isEnabled() {
return enabled;
}
@@ -93,4 +103,20 @@ public class ThreadPoolProperties {
public void setKeepAliveSeconds(int keepAliveSeconds) {
this.keepAliveSeconds = keepAliveSeconds;
}
public boolean isWaitForTasksToCompleteOnShutdown() {
return waitForTasksToCompleteOnShutdown;
}
public void setWaitForTasksToCompleteOnShutdown(boolean waitForTasksToCompleteOnShutdown) {
this.waitForTasksToCompleteOnShutdown = waitForTasksToCompleteOnShutdown;
}
public long getAwaitTerminationMillis() {
return awaitTerminationMillis;
}
public void setAwaitTerminationMillis(long awaitTerminationMillis) {
this.awaitTerminationMillis = awaitTerminationMillis;
}
}