網站首頁 編程語言 正文
一般情況下定時任務的使用常見的兩個組件:xxl-job和quartz,這兩種需要引用相應的依賴,針對對定時任務較為復雜和依賴性較高的系統(tǒng)
但是如果項目中使用定時任務的場景不多,避免項目過于臃腫和復雜,但要求可配置、可刪除、可啟停用的
定時任務的必要字段
TASK_NAME: 定時任務名稱;
TASK_CRON:定時任務執(zhí)行頻率,cron表達式
TASK_BEAN: 執(zhí)行定時任務的Bean名稱
TASK_MOTHOD: 執(zhí)行定時任務的方法名
一、創(chuàng)建線程池并設置參數
ThreadPoolTaskScheduler:
主要用于任務調度,可以按照時間間隔或Cron表達式來執(zhí)行任務。
繼承自TaskScheduler接口,并實現了AsyncTaskExecutor接口。
它基于線程池來執(zhí)行任務,并且可以根據需要調度任務的執(zhí)行。特點:
強調任務調度和時間控制。
適用于需要按照特定時間間隔或規(guī)則執(zhí)行任務的場景。
其他線程:
主要用于執(zhí)行異步任務和多線程任務。
專注于線程池的管理和配置,如線程池的大小、隊列容量以及線程的創(chuàng)建和銷毀策略特點:
強調線程池的管理和異步任務的執(zhí)行。
適用于需要并發(fā)執(zhí)行大量異步任務的場景。
@Configuration
public class SchedulingConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(4);
taskScheduler.setRemoveOnCancelPolicy(true);
taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-");
return taskScheduler;
}
}
二、添加 ScheduledFuture 的包裝類
ScheduledTaskFuture :
主要用于處理和控制定時任務的執(zhí)行結果和執(zhí)行狀態(tài)。它提供了異步執(zhí)行結果的獲取、任務執(zhí)行狀態(tài)的控制、任務執(zhí)行結果的獲取和異常處理、任務的取消以及超時獲取任務結果等功能,使得你可以更加方便地管理和控制定時任務的執(zhí)行。1、可以通過ScheduledTaskFuture來獲取定時任務執(zhí)行后的結果,查詢定時任務是否已完成(isDone()方法)、是否已被取消(isCancelled()方法)或者是否正在執(zhí)行(!isDone() && !isCancelled())。
2、可以調用ScheduledTaskFuture的get()方法來獲取定時任務執(zhí)行的結果。
3、可以調用cancel(boolean mayInterruptIfRunning)方法來取消定時任務的執(zhí)行。如果參數mayInterruptIfRunning為true,嘗試中斷正在執(zhí)行的任務;如果為false,則正在執(zhí)行的任務不會被中斷,但是等待執(zhí)行的任務會被取消
@Component
public final class ScheduledTaskFuture {
public volatile ScheduledFuture<?> scheduledFuture;
public void cancel(){
ScheduledFuture<?> future = this.scheduledFuture;
if (future != null) {
future.cancel(true);
}
}
}
三、定時任務實體類
public class DismTimedTask {
/**
* 任務ID
*/
@Id
@Column(name = "TASK_ID")
private Long taskId;
/**
* 任務名稱
*/
@Column(name = "TASK_NAME")
private String taskName;
/**
* 任務執(zhí)行頻率
*/
@Column(name = "TASK_CRON")
private String taskCron;
/**
* 時間范圍
*/
@Column(name = "TASK_BEAN")
private int taskBean;
/**
* 是否包含
*/
@Column(name = "TASK_METHOD_NAME")
private String taskMethodName;
/**
* 模板狀態(tài)
*/
@Column(name = "STATUS")
private String status;
}
四、任務的執(zhí)行
public class SchedulingRunnable implements Runnable{
/**
* 執(zhí)行定時任務的Bean名稱
*/
private String beanName;
/**
* 執(zhí)行定時任務的方法名稱
*/
private String methodName;
/**
* 定時任務的參數、可定義為其他類型
*/
private Long taskId;
public SchedulingRunnable(String beanName, String methodName, Long taskId) {
this.beanName = beanName;
this.methodName = methodName;
this.taskId = taskId;
}
@Override
public void run() {
log.info("定時任務開始執(zhí)行 - bean: {}, 方法: {}", beanName, methodName);
try {
Object target = SpringContextUtils.getBean(beanName);
if (taskId == null || taskId == 0L) {
// 無參的
Method method = target.getClass().getMethod(methodName);
method.invoke(target);
} else {
//有參的
Method method = target.getClass().getMethod(methodName, Long.class);
method.invoke(target, taskId);
}
} catch (Exception ex) {
log.error(String.format("定時任務執(zhí)行異常-bean: %s, 方法: %s", beanName, methodName));
log.error("異常:" + ex);
}
log.info("定時任務執(zhí)行結束 - bean: {}, 方法: {}", beanName, methodName);
}
}
五、定時任務的創(chuàng)建、刪除操作
@Service
@Slf4j
public class TimedTaskServiceImpl implements TimedTaskService {
private final Map<Long, ScheduledTaskFuture> scheduledTasks = new ConcurrentHashMap<>(16);
@Resource
private TaskScheduler taskScheduler;
/**
* 更新定時任務
* @author Liyh
* @date 2024/06/17 09:56
* @param timedTask
*/
@Transactional(rollbackFor = Exception.class)
public void updateTimedTask(TimedTask timedTask) {
//定時任務執(zhí)行Bean
SchedulingRunnable schedulingRunnable = new SchedulingRunnable(timedTask.getBean(), timedTask.getMothod(), timedTask.getTaskId());
CronTask cronTask = new CronTask(schedulingRunnable, timedTask.getTaskCron());
if ("1".equals(timedTask.getStatus())) {
// 啟用
// 如果定時任務已經存在,先刪后增,
if (this.scheduledTasks.containsKey(timedTask.getTaskId())){
removeCronTask(timedTask.getTaskId());
}
this.scheduledTasks.put(timedTask.getTaskId(), scheduledTask(cronTask));
} else {
// 停用
removeCronTask(timedTask.getTaskId());
}
}
/**
* 刪除定時任務
* @author Liyh
* @date 2024/06/11 17:41
* @param taskId
*/
public void removeCronTask(Long taskId){
ScheduledTaskFuture scheduledTask = this.scheduledTasks.remove(taskId);
if (scheduledTask != null) {
scheduledTask.cancel();
}
}
/**
* 創(chuàng)建定時任務
* @author Liyh
* @date 2024/06/11 17:41
* @param cronTask
* @return ScheduledTaskFuture
*/
public ScheduledTaskFuture scheduledTask(CronTask cronTask){
ScheduledTaskFuture scheduledTask = new ScheduledTaskFuture();
scheduledTask.scheduledFuture = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());
return scheduledTask;
}
}
/*刪除任務時執(zhí)行removeCronTask方法即可*/
六、獲取Bean的工具類
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
}
7、程序啟動時加載數據庫中啟用的任務
@Component
public class TimedTaskRunner implements CommandLineRunner {
@Resource
private TimedTaskService timedTaskService;
@Override
public void run(String... args) throws Exception {
timedTaskService.runAllTimedTask();
}
}
具體實現類方法
public void runAllTimedTask() {
List<DismTimedTask> timedTaskList = timedTaskDao.getDismTimedTaskByStatus("1");
if (timedTaskList != null && !timedTaskList.isEmpty()) {
for (DismTimedTask timedTask : timedTaskList) {
SchedulingRunnable schedulingRunnable = new SchedulingRunnable(null, "taskRunning", timedTask.getTaskId());
CronTask cronTask = new CronTask(schedulingRunnable, timedTask.getTaskCron());
scheduledTask(cronTask);
this.scheduledTasks.put(timedTask.getTaskId(), scheduledTask(cronTask));
log.info("定時任務已加載完畢...");
}
}
}
原文鏈接:https://blog.csdn.net/saonian0929/article/details/139850453
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-08-24 k8s部署redis哨兵的實現_Redis
- 2022-07-04 pandas讀取中文xlsx文件出現的問題_python
- 2022-12-22 Qt實現繪制一個簡單多邊形的示例代碼_C 語言
- 2022-05-27 numpy模塊中axis的理解與使用_python
- 2022-05-11 深入理解AQS之Semaphore&CountDownLatch&Cyclic詳解
- 2022-06-08 Golang原生rpc(rpc服務端源碼解讀)_Golang
- 2022-11-08 PostgreSQL查看帶有綁定變量SQL的通用方法詳解_PostgreSQL
- 2023-01-15 詳解Qt中線程的使用方法_C 語言
- 欄目分類
-
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支