Skip to content

Commit

Permalink
refactor: 应用关闭,关闭自定义线程池ScheduledExecutorService
Browse files Browse the repository at this point in the history
* 程序结束,关闭ScheduledExecutorService 线程池。
  • Loading branch information
wangjiangtao2 authored and Charles7c committed Apr 15, 2024
1 parent dbb7a63 commit c4051a6
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
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;
Expand All @@ -30,9 +31,13 @@
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;

/**
* 线程池自动配置
Expand Down Expand Up @@ -69,6 +74,11 @@ public ThreadPoolTaskExecutor threadPoolTaskExecutor(ThreadPoolProperties proper
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;
}
Expand All @@ -88,7 +98,65 @@ protected void afterExecute(Runnable runnable, Throwable throwable) {
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();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ public class ThreadPoolProperties {
*/
private int keepAliveSeconds = 300;

/**
* 关闭线程池是否等待任务完成
*/
private boolean waitForTasksToCompleteOnShutdown = false;

/**
* 执行器在关闭时阻塞的最长毫秒数,以等待剩余任务完成执行。
*/
private long awaitTerminationMillis = 0;

public boolean isEnabled() {
return enabled;
}
Expand Down Expand Up @@ -93,4 +103,20 @@ public int getKeepAliveSeconds() {
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;
}
}

0 comments on commit c4051a6

Please sign in to comment.