一、話不多說,上代碼
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
@EnableScheduling
@Configuration
public class LianScheduleConfig implements SchedulingConfigurer {
/*獲取當前系統的CPU數,根據CPU數初始化線程*/
private static final int PROCESSORS_COUNT = Runtime.getRuntime().availableProcessors();
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
// <核心線程數>線程池創建時候初始化的線程數
threadPool.setCorePoolSize(PROCESSORS_COUNT);
// <最大線程數>線程池最大的線程數,只有在<緩衝隊列數>滿了之後纔會申請超過核心線程數的線程
threadPool.setMaxPoolSize(PROCESSORS_COUNT * 2);
// <緩衝隊列數>線程池所使用的緩衝隊列
threadPool.setQueueCapacity(PROCESSORS_COUNT * 10);
// 當線程數超過最大線程數時,處理方式
// new ThreadPoolExecutor.AbortPolicy():丟棄任務並拋出RejectedExecutionException異常
// new ThreadPoolExecutor.DiscardPolicy():也是丟棄任務,但是不拋出異常
// new ThreadPoolExecutor.DiscardOldestPolicy():丟棄<緩衝隊列數>最前面的任務,然後重新嘗試執行任務
// new ThreadPoolExecutor.CallerRunsPolicy():由調用線程處理該任務,一般會阻塞,說白了就是沒有線程作用~
threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// <核心線程數>之外的線程在空閒時間60秒到達之後會被銷燬
threadPool.setKeepAliveSeconds(60);
// <核心線程數>之外的線程在存活時間10分鐘到達之後會被銷燬
threadPool.setAwaitTerminationSeconds(10 * 60);
// 線程池關閉的時候等待所有任務都完成再繼續銷燬其他的Bean,這樣這些異步任務的銷燬就會先於Redis線程池的銷燬。
threadPool.setWaitForTasksToCompleteOnShutdown(true);
// 線程前綴
threadPool.setThreadNamePrefix("LianScheduled-");
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(PROCESSORS_COUNT, threadPool));
}
}
二、爲什麼要配置?
1、@Scheduled默認不配置的時候是使用單線程處理,比如你有兩個方法A和B使用定時任務@Scheduled註解,那麼在運行時,A方法執行完畢後,纔會執行B方法,也就是如果A方法在執行的時候堵塞了,B方法就不會執行~