最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot定時(shí)任務(wù)動(dòng)態(tài)擴(kuò)展ScheduledTaskRegistrar詳解

 更新時(shí)間:2023年01月12日 15:12:56   作者:昵稱為空C  
這篇文章主要為大家介紹了SpringBoot定時(shí)任務(wù)動(dòng)態(tài)擴(kuò)展ScheduledTaskRegistrar類示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

摘要

本文主要介紹基于SpringBoot定時(shí)任務(wù)ScheduledTaskRegistrar的動(dòng)態(tài)擴(kuò)展,實(shí)現(xiàn)定時(shí)任務(wù)的動(dòng)態(tài)新增和刪除。

ScheduledTaskRegistrar類簡(jiǎn)要描述

平常使用方式配置

  • Application啟動(dòng)類上添加注解@EnableScheduling
@EnableScheduling
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 在需要定時(shí)的方法上添加定時(shí)注解@Scheduled(cron = "0/10 * * * * ?")
@Slf4j
@Component
public class OtherScheduler {
    @Scheduled(cron = "0/10 * * * * ?")
    public void print(){
        log.info("每10S打印一次");
    }
    @Scheduled(cron = "0/5 * * * * ?")
    public void print5(){
        log.info("每5S打印一次");
    }
}

原理分析

默認(rèn)的方式啟動(dòng)把ScheduledAnnotationBeanPostProcessor該類實(shí)例化到SpringBootBean管理中,并且該類持有一個(gè)ScheduledTaskRegistrar屬性,然后掃描出來(lái)?yè)碛?code>@Scheduled注解的方法,添加到定時(shí)任務(wù)中。

  • 添加定時(shí)任務(wù)到列表中

掃描到@Scheduled注解的時(shí)候調(diào)用了該方法添加任務(wù)

public void addCronTask(Runnable task, String expression) {
	if (!CRON_DISABLED.equals(expression)) {
		addCronTask(new CronTask(task, expression));
	}
}
  • 啟動(dòng)定時(shí)任務(wù)

在對(duì)象實(shí)例化完成后,調(diào)用了afterPropertiesSet方法,該方法實(shí)際使用中執(zhí)行了

public void afterPropertiesSet() {
	scheduleTasks();
}
protected void scheduleTasks() {
	if (this.taskScheduler == null) {
		this.localExecutor = Executors.newSingleThreadScheduledExecutor();
		this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
	}
	if (this.triggerTasks != null) {
		for (TriggerTask task : this.triggerTasks) {
			addScheduledTask(scheduleTriggerTask(task));
		}
	}
	if (this.cronTasks != null) {
		for (CronTask task : this.cronTasks) {
			addScheduledTask(scheduleCronTask(task));
		}
	}
	if (this.fixedRateTasks != null) {
		for (IntervalTask task : this.fixedRateTasks) {
			addScheduledTask(scheduleFixedRateTask(task));
		}
	}
	if (this.fixedDelayTasks != null) {
		for (IntervalTask task : this.fixedDelayTasks) {
			addScheduledTask(scheduleFixedDelayTask(task));
		}
	}
}
private void addScheduledTask(@Nullable ScheduledTask task) {
	if (task != null) {
		this.scheduledTasks.add(task);
	}
}
// 啟動(dòng)任務(wù)核心方法
public ScheduledTask scheduleCronTask(CronTask task) {
	ScheduledTask scheduledTask = this.unresolvedTasks.remove(task);
	boolean newTask = false;
	if (scheduledTask == null) {
		scheduledTask = new ScheduledTask(task);
		newTask = true;
	}
	if (this.taskScheduler != null) {
		scheduledTask.future = this.taskScheduler.schedule(task.getRunnable(), task.getTrigger());
	}
	else {
		addCronTask(task);
		this.unresolvedTasks.put(task, scheduledTask);
	}
	return (newTask ? scheduledTask : null);
}

DynamicScheduledTaskRegistrar 動(dòng)態(tài)任務(wù)注冊(cè)類

下面改動(dòng)主要涉及到線程池?cái)?shù)量、新增任務(wù)、刪除任務(wù)、銷毀任務(wù)四個(gè)方面;

public class DynamicScheduledTaskRegistrar extends ScheduledTaskRegistrar {
    private static final Logger log = LoggerFactory.getLogger(DynamicScheduledTaskRegistrar.class);
    private final Map<String,ScheduledTask> scheduledTaskMap = new LinkedHashMap<>(16);
    public DynamicScheduledTaskRegistrar(){
        super();
        // 兩種實(shí)現(xiàn)方案
        //ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        //TaskScheduler taskScheduler = new ConcurrentTaskScheduler(scheduledExecutorService);
        // 第二種實(shí)現(xiàn)方案
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(8);
        taskScheduler.setRemoveOnCancelPolicy(true);
        taskScheduler.setThreadNamePrefix("dynamic-scheduled-task-");
        taskScheduler.initialize();
        this.setScheduler(taskScheduler);
    }
    /**
     * 新增任務(wù)
     * @param taskName
     * @param cron
     * @param runnable
     */
    public Boolean addCronTask(String taskName,String cron,Runnable runnable){
        if(scheduledTaskMap.containsKey(taskName)){
            log.error("定時(shí)任務(wù)["+ taskName+"]已存在,添加失敗");
            return Boolean.FALSE;
        }
        CronTask cronTask = new CronTask(runnable,cron);
        ScheduledTask scheduledTask = this.scheduleCronTask(cronTask);
        scheduledTaskMap.put(taskName,scheduledTask);
        log.info("定時(shí)任務(wù)["+taskName+"]新增成功");
        return Boolean.TRUE;
    }
    /**
     * 刪除任務(wù)
     * @param taskName
     */
    public void cancelCronTask(String taskName){
        ScheduledTask scheduledTask = scheduledTaskMap.get(taskName);
        if(null != scheduledTask){
            scheduledTask.cancel();
            scheduledTaskMap.remove(taskName);
        }
        log.info("定時(shí)任務(wù)["+taskName+"]刪除成功");
    }
    @Override
    public void destroy() {
        super.destroy();
        scheduledTaskMap.values().forEach(ScheduledTask::cancel);
    }
}

線程池?cái)?shù)量問題

由于默認(rèn)是單線程的,如果任務(wù)阻塞時(shí)間過長(zhǎng)則會(huì)導(dǎo)致后續(xù)的任務(wù)阻塞,所以盡量是異步任務(wù)或者是線程池?cái)?shù)量大一點(diǎn),則可以避免這個(gè)問題

DynamicScheduledTaskService

@Service
public class DynamicScheduledTaskService {
    private static final Logger log = LoggerFactory.getLogger(DynamicScheduledTaskService.class);
    private final DynamicScheduledTaskRegistrar dynamicScheduledTaskRegistrar = new DynamicScheduledTaskRegistrar();
    /**
     * 新增任務(wù)
     * @param taskName
     * @param cron
     */
    public void add(String taskName,String cron){
        Boolean result = dynamicScheduledTaskRegistrar.addCronTask(taskName,cron,() -> print(taskName));
        log.info("定時(shí)任務(wù)添加結(jié)果:" + result);
    }
    /**
     * 取消任務(wù)
     * @param taskName
     */
    public void cancel(String taskName){
        dynamicScheduledTaskRegistrar.cancelCronTask(taskName);
    }
    private void print(String taskName){
        log.info(taskName+"開始");
        try{
            Thread.sleep(9000L);
            log.info(taskName+"結(jié)束111");
        }catch (Exception ex){
        }
        log.info(taskName+"結(jié)束");
    }
}

SchedulerController

@RestController
@RequestMapping(value = "scheduler")
public class SchedulerController {
    @Autowired
    private DynamicScheduledTaskService dynamicScheduledTaskService;
    @GetMapping(value = "add")
    public Object add(String taskName,String cron){
        dynamicScheduledTaskService.add(taskName,cron);
        return "SUCCESS";
    }
    @GetMapping(value = "cancel")
    public Object cancel(String jobName){
        dynamicScheduledTaskService.cancel(jobName);
        return "SUCCESS";
    }
}

測(cè)試結(jié)果

新增的任務(wù)都睡眠了9S

新增調(diào)度任務(wù)

刪除調(diào)度任務(wù)

以上就是SpringBoot定時(shí)任務(wù)動(dòng)態(tài)擴(kuò)展ScheduledTaskRegistrar詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot ScheduledTaskRegistrar的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

苏尼特左旗| 文山县| 芮城县| 潮州市| 图木舒克市| 清水河县| 龙岩市| 蓬莱市| 涡阳县| 康平县| 恭城| 永宁县| 隆安县| 玉溪市| 新昌县| 南华县| 观塘区| 广州市| 边坝县| 定日县| 疏勒县| 崇礼县| 渝北区| 安庆市| 肥西县| 涿州市| 乌拉特中旗| 开封市| 凤冈县| 贵定县| 平阳县| 阿巴嘎旗| 定远县| 区。| 仪征市| 图木舒克市| 上林县| 河东区| 麻城市| 曲沃县| 威海市|