自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

探索動(dòng)態(tài)執(zhí)行的計(jì)劃任務(wù)-DynamicSchedule

開發(fā) 前端
通過上述方法,我們可以在 Spring Boot 應(yīng)用中實(shí)現(xiàn)動(dòng)態(tài)計(jì)劃任務(wù),使得任務(wù)的執(zhí)行更加靈活可控。還實(shí)驗(yàn)了幾種不同的方式,比如每秒輪詢數(shù)據(jù)庫(kù)、手動(dòng)計(jì)算cron表達(dá)式 的執(zhí)行時(shí)間。感覺就屬這個(gè)事件驅(qū)動(dòng)的方式最優(yōu)雅。

背景

在現(xiàn)代軟件開發(fā)中,計(jì)劃任務(wù)是一種常見的需求。無論是定時(shí)發(fā)送郵件、定期清理緩存,還是執(zhí)行數(shù)據(jù)同步,計(jì)劃任務(wù)都能幫助我們自動(dòng)化這些重復(fù)性工作。

最近有一個(gè)需求,用戶想要自己設(shè)定定時(shí)時(shí)間,來動(dòng)態(tài)的執(zhí)行定時(shí)任務(wù)。 很離譜,原來每天晚上12點(diǎn)定時(shí)執(zhí)行的幾個(gè)數(shù)據(jù)同步、數(shù)據(jù)清理任務(wù),想不通用戶要這個(gè)功能干啥!?。?/p>

探索歷程

原本的cron表達(dá)式,是直接寫死到代碼里的,顯然不能動(dòng)態(tài)的修改。

如果采用配置文件的方式,每次改動(dòng)要重啟項(xiàng)目,或者再寫個(gè)定時(shí)任務(wù),每秒讀取文件內(nèi)容,也不太合適。

如果引入分布式任務(wù)調(diào)度平臺(tái),比如xxl-job、power-job、snail-job,又覺得太復(fù)雜。

選擇采用放到數(shù)據(jù)庫(kù)的方式,實(shí)現(xiàn)過程中,發(fā)現(xiàn)并不是很順利,寫一篇文章記錄一下這次的過程。

原本的實(shí)現(xiàn)

@Scheduled(cron = "0/5 * * * * *")  
public void demo() {  
    System.out.println(LocalDateTime.now());  
}

結(jié)果

圖片圖片

動(dòng)態(tài)設(shè)置

配置類

@Component  
@RequiredArgsConstructor  
public class JobConfig implements SchedulingConfigurer {  
  
    private final ITestJobService jobService;  
  
    @Override  
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {  
        taskRegistrar.addTriggerTask(  
                //1.添加任務(wù)內(nèi)容(Runnable)  
                () -> System.out.println("執(zhí)行動(dòng)態(tài)定時(shí)任務(wù)1: " + LocalDateTime.now()),  
                //2.設(shè)置執(zhí)行周期(Trigger)  
                triggerContext -> {  
                    TestJob job = jobService.getById(1L);  
                    return new CronTrigger(job.getCron()).nextExecutionTime(triggerContext).toInstant();  
                }  
        );  
    }  
}

修改入口

@GetMapping("upd")  
public String upd(@RequestParam("cron") String cron) {  
    jobService.updateById(new TestJob(1, cron));  
    System.out.println("修改時(shí)間:"+ LocalDateTime.now());  
    return "success";  
}

將 0/10 * * * * * 改為 0/5 * * * * *

結(jié)果

圖片圖片

可以看出來 修改的時(shí)間是 15:01 ,但是下次執(zhí)行時(shí)間還是間隔了10秒,第二次之后的時(shí)間才是間隔5秒。 更新結(jié)果有一個(gè)周期的延遲。

在這種情況下,延遲還算可以接收,但是周期如果是一天、一周,那生效周期就太長(zhǎng)了,需要一種即時(shí)生效的方法。

即時(shí)生效

實(shí)現(xiàn)方案是,以事件驅(qū)動(dòng),動(dòng)態(tài)修改定時(shí)任務(wù)。

定義事件

@Getter  
public class ScheduleTaskUpdateEvent extends ApplicationEvent {  
  
    private final Integer taskId;  
  
    public ScheduleTaskUpdateEvent(Object source, Integer taskId) {  
        super(source);  
        this.taskId = taskId;  
    }  
}

構(gòu)造調(diào)度任務(wù)程序

@Configuration  
public class SchedulerConfig {  
  
    @Bean  
    public ThreadPoolTaskScheduler taskScheduler() {  
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();  
        scheduler.setPoolSize(10); // 設(shè)置線程池大小  
        scheduler.setThreadNamePrefix("scheduled-task-");  
        scheduler.initialize();  
        return scheduler;  
    }  
}

動(dòng)態(tài)任務(wù)配置

@Component  
public class DynamicScheduleTaskConfig implements ApplicationListener<ScheduleTaskUpdateEvent> {  
  
    @Resource  
    private ITestJobService jobService;  
  
    @Resource  
    private TaskScheduler taskScheduler;  
  
    private final Map<Integer, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();  
  
    @PostConstruct  
    private void initializeTasks() {  
        List<TestJob> list = jobService.list();  
        list.forEach(job -> {  
            ScheduledFuture<?> future = scheduleTask(job);  
            scheduledTasks.put(job.getId(), future);  
        });  
    }  
  
    // 根據(jù)任務(wù)配置創(chuàng)建任務(wù)  
    private ScheduledFuture<?> scheduleTask(TestJob job) {  
        System.out.println("創(chuàng)建新的定時(shí)任務(wù),id:" + job.getId() + ", cron: " + job.getCron());  
        return taskScheduler.schedule(  
                () -> System.out.println("執(zhí)行動(dòng)態(tài)定時(shí)任務(wù)2: " + LocalDateTime.now()),  
                triggerContext -> {  
                    return new CronTrigger(job.getCron()).nextExecutionTime(triggerContext).toInstant();  
                }  
        );  
    }  
  
    @Override  
    public void onApplicationEvent(ScheduleTaskUpdateEvent event) {  
        System.out.println("收到修改定時(shí)任務(wù)事件,任務(wù)id:" + event.getTaskId());  
        // 取消并移除舊任務(wù)  
        ScheduledFuture<?> future = scheduledTasks.get(event.getTaskId());  
        if (future != null) {  
            future.cancel(false);  
            scheduledTasks.remove(event.getTaskId());  
        }  
  
        // 獲取最新的任務(wù)配置并重新注冊(cè)該任務(wù)  
        TestJob job = jobService.getById(event.getTaskId());  
        ScheduledFuture<?> newFuture = scheduleTask(job);  
        scheduledTasks.put(job.getId(), newFuture);  
    }  
}

修改接口,增加事件

@GetMapping("upd")  
public String upd(@RequestParam("cron") String cron) {  
    jobService.updateById(new TestJob(1, cron));  
    eventPublisher.publishEvent(new ScheduleTaskUpdateEvent(this, 1));  
    System.out.println("修改時(shí)間:"+ LocalDateTime.now());  
    return "success";  
}

結(jié)果

圖片圖片

可以看到,在收到修改任務(wù)的事件后,直接刪除了原來的定時(shí)任務(wù),創(chuàng)建了一個(gè)新的執(zhí)行任務(wù),即時(shí)生效,不需要等待一個(gè)執(zhí)行周期就可立即執(zhí)行。

小結(jié)

通過上述方法,我們可以在 Spring Boot 應(yīng)用中實(shí)現(xiàn)動(dòng)態(tài)計(jì)劃任務(wù),使得任務(wù)的執(zhí)行更加靈活可控。

還實(shí)驗(yàn)了幾種不同的方式,比如每秒輪詢數(shù)據(jù)庫(kù)、手動(dòng)計(jì)算cron表達(dá)式 的執(zhí)行時(shí)間。感覺就屬這個(gè)事件驅(qū)動(dòng)的方式最優(yōu)雅。

責(zé)任編輯:武曉燕 來源: Java技術(shù)指北
相關(guān)推薦

2010-01-07 11:19:45

Linux計(jì)劃任務(wù)

2010-03-09 17:45:11

Linux計(jì)劃任務(wù)

2010-01-20 10:27:16

Linuxcrond命

2017-03-27 08:30:00

Windows 8Windows計(jì)劃任務(wù)

2021-01-08 08:47:56

Saltstack架構(gòu)管理服務(wù)器

2023-10-06 12:15:02

2017-11-23 09:00:02

Linuxcron計(jì)劃任務(wù)

2017-07-14 11:50:15

Windows 10Windows計(jì)劃任務(wù)

2011-04-01 09:17:01

備份cactiwindows

2017-06-09 13:17:04

Linuxcronanacron

2019-05-29 08:00:00

Linux計(jì)劃任務(wù)cron

2021-01-14 16:14:06

Python爬蟲代碼

2010-05-04 12:29:15

Oracle數(shù)據(jù)庫(kù)

2023-06-29 07:55:52

Quartz.Net開源

2010-05-04 12:43:11

Oracle數(shù)據(jù)庫(kù)

2025-01-16 08:07:05

cron可視化管理器開源

2010-11-15 09:10:43

CrontabLinux計(jì)劃任務(wù)

2024-11-11 10:58:03

Spring接口編程

2021-03-16 21:30:27

Windows 10Windows操作系統(tǒng)

2010-01-07 11:10:00

cron配置計(jì)劃
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)