日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

spring實現定時任務的動態可配置、可刪除、可啟用停用功能

作者:街角等待 更新時間: 2024-07-13 編程語言

一般情況下定時任務的使用常見的兩個組件:xxl-job和quartz,這兩種需要引用相應的依賴,針對對定時任務較為復雜和依賴性較高的系統
但是如果項目中使用定時任務的場景不多,避免項目過于臃腫和復雜,但要求可配置、可刪除、可啟停用的

定時任務的必要字段

TASK_NAME: 定時任務名稱;
TASK_CRON:定時任務執行頻率,cron表達式
TASK_BEAN: 執行定時任務的Bean名稱
TASK_MOTHOD: 執行定時任務的方法名

一、創建線程池并設置參數

ThreadPoolTaskScheduler:

主要用于任務調度,可以按照時間間隔或Cron表達式來執行任務。
繼承自TaskScheduler接口,并實現了AsyncTaskExecutor接口。
它基于線程池來執行任務,并且可以根據需要調度任務的執行。

特點:
強調任務調度和時間控制。
適用于需要按照特定時間間隔或規則執行任務的場景。

其他線程:

主要用于執行異步任務和多線程任務。
專注于線程池的管理和配置,如線程池的大小、隊列容量以及線程的創建和銷毀策略

特點:
強調線程池的管理和異步任務的執行。
適用于需要并發執行大量異步任務的場景。

@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 :
主要用于處理和控制定時任務的執行結果和執行狀態。它提供了異步執行結果的獲取、任務執行狀態的控制、任務執行結果的獲取和異常處理、任務的取消以及超時獲取任務結果等功能,使得你可以更加方便地管理和控制定時任務的執行。

1、可以通過ScheduledTaskFuture來獲取定時任務執行后的結果,查詢定時任務是否已完成(isDone()方法)、是否已被取消(isCancelled()方法)或者是否正在執行(!isDone() && !isCancelled())。
2、可以調用ScheduledTaskFuture的get()方法來獲取定時任務執行的結果。
3、可以調用cancel(boolean mayInterruptIfRunning)方法來取消定時任務的執行。如果參數mayInterruptIfRunning為true,嘗試中斷正在執行的任務;如果為false,則正在執行的任務不會被中斷,但是等待執行的任務會被取消

@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;

    /**
     * 任務執行頻率
     */
    @Column(name = "TASK_CRON")
    private String taskCron;

    /**
     * 時間范圍
     */
    @Column(name = "TASK_BEAN")
    private int taskBean;

    /**
     * 是否包含
     */
    @Column(name = "TASK_METHOD_NAME")
    private String taskMethodName;
    
    /**
     * 模板狀態
     */
    @Column(name = "STATUS")
    private String status;
}

四、任務的執行

public class SchedulingRunnable implements Runnable{
	/**
	* 執行定時任務的Bean名稱
	*/
    private String beanName;
	/**
	* 執行定時任務的方法名稱
	*/
    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("定時任務開始執行 - 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("定時任務執行異常-bean: %s, 方法: %s", beanName, methodName));
            log.error("異常:" + ex);
        }
        log.info("定時任務執行結束 - bean: {}, 方法: {}", beanName, methodName);
    }
}

五、定時任務的創建、刪除操作

@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) {
    //定時任務執行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();
        }
    }

    /**
     * 創建定時任務
     * @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;
    }
}
/*刪除任務時執行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

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新