- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- SpringBoot實(shí)現動(dòng)態(tài)多線(xiàn)程并發(fā)定時(shí)任務(wù)
本文實(shí)例為大家分享了SpringBoot實(shí)現動(dòng)態(tài)多線(xiàn)程并發(fā)定時(shí)任務(wù)的具體代碼,供大家參考,具體內容如下
實(shí)現定時(shí)任務(wù)有多種方式,使用spring自帶的,繼承SchedulingConfigurer的方式。
1、啟動(dòng)類(lèi)
在啟動(dòng)類(lèi)添加注解@EnableScheduling開(kāi)啟,不然不起用做。
2、新建任務(wù)類(lèi)
添加注解@Component注冊到spring的容器中。
package com.example.demo.task; import com.example.demo.entity.MyTask; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.CronTask; import org.springframework.scheduling.config.ScheduledTaskRegistrar; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.annotation.PreDestroy; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledFuture; /** * @path:com.example.demo.task.ScheduledTask.java * @className:ScheduledTask.java * @description:定時(shí)任務(wù) * @author:tanyp * @dateTime:2020/7/23 21:37 * @editNote: */ @Slf4j @Component public class ScheduledTask implements SchedulingConfigurer { private volatile ScheduledTaskRegistrar registrar; private final ConcurrentHashMap<String, ScheduledFuture<?>> scheduledFutures = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, CronTask> cronTasks = new ConcurrentHashMap<>(); /** * 默認啟動(dòng)10個(gè)線(xiàn)程 */ private static final Integer DEFAULT_THREAD_POOL = 10; @Override public void configureTasks(ScheduledTaskRegistrar registrar) { registrar.setScheduler(Executors.newScheduledThreadPool(DEFAULT_THREAD_POOL)); this.registrar = registrar; } @PreDestroy public void destroy() { this.registrar.destroy(); } /** * @methodName:refreshTask * @description:初始化任務(wù) * 1、從數據庫獲取執行任務(wù)的集合【TxTask】 * 2、通過(guò)調用 【refresh】 方法刷新任務(wù)列表 * 3、每次數據庫中的任務(wù)發(fā)生變化后重新執行【1、2】 * @author:tanyp * @dateTime:2020/7/23 21:37 * @Params: [tasks] * @Return: void * @editNote: */ public void refreshTask(List<MyTask> tasks) { // 刪除已經(jīng)取消任務(wù) scheduledFutures.keySet().forEach(key -> { if (Objects.isNull(tasks) || tasks.size() == 0) { scheduledFutures.get(key).cancel(false); scheduledFutures.remove(key); cronTasks.remove(key); return; } tasks.forEach(task -> { if (!Objects.equals(key, task.getTaskId())) { scheduledFutures.get(key).cancel(false); scheduledFutures.remove(key); cronTasks.remove(key); return; } }); }); // 添加新任務(wù)、更改執行規則任務(wù) tasks.forEach(txTask -> { String expression = txTask.getExpression(); // 任務(wù)表達式為空則跳過(guò) if (StringUtils.isEmpty(expression)) { return; } // 任務(wù)已存在并且表達式未發(fā)生變化則跳過(guò) if (scheduledFutures.containsKey(txTask.getTaskId()) && cronTasks.get(txTask.getTaskId()).getExpression().equals(expression)) { return; } // 任務(wù)執行時(shí)間發(fā)生了變化,則刪除該任務(wù) if (scheduledFutures.containsKey(txTask.getTaskId())) { scheduledFutures.get(txTask.getTaskId()).cancel(false); scheduledFutures.remove(txTask.getTaskId()); cronTasks.remove(txTask.getTaskId()); } CronTask task = new CronTask(new Runnable() { @Override public void run() { // 執行業(yè)務(wù)邏輯 try { log.info("執行單個(gè)任務(wù),任務(wù)ID【{}】執行規則【{}】", txTask.getTaskId(), txTask.getExpression()); System.out.println("==========================執行任務(wù)============================="); } catch (Exception e) { log.error("執行發(fā)送消息任務(wù)異常,異常信息:{}", e); } } }, expression); ScheduledFuture<?> future = registrar.getScheduler().schedule(task.getRunnable(), task.getTrigger()); cronTasks.put(txTask.getTaskId(), task); scheduledFutures.put(txTask.getTaskId(), future); }); } }
3、創(chuàng )建自啟動(dòng)任務(wù)類(lèi)
package com.example.demo.task; import com.example.demo.task.ScheduledTask; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; /** * @path:com.example.demo.task.MyApplicationRunner.java * @className:ScheduledTask.java * @description:自啟動(dòng) * @author:tanyp * @dateTime:2020/7/23 21:37 * @editNote: */ @Slf4j @Component public class MyApplicationRunner implements ApplicationRunner { @Autowired private ScheduledTask scheduledTask; @Override public void run(ApplicationArguments args) throws Exception { log.info("================項目啟動(dòng)初始化定時(shí)任務(wù)====開(kāi)始==========="); /** * 初始化三個(gè)任務(wù): * 1、10秒執行一次 * 2、15秒執行一次 * 3、20秒執行一次 */ List<MyTask> tasks = Arrays.asList( MyTask.builder().taskId("10001").expression("*/10 * * * * ?").build(), MyTask.builder().taskId("10002").expression("*/15 * * * * ?").build(), MyTask.builder().taskId("10003").expression("*/20 * * * * ?").build() ); scheduledTask.refreshTask(tasks); log.info("================項目啟動(dòng)初始化定時(shí)任務(wù)====完成=========="); } }
4、實(shí)體
package com.example.demo.entity; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; /** * @path:com.example.demo.entity.MyTask.java * @className:MyTask.java * @description:任務(wù)實(shí)體 * @author:tanyp * @dateTime:2020/7/23 21:41 * @editNote: */ @Data @Builder @AllArgsConstructor @NoArgsConstructor public class MyTask { /** * 任務(wù)id */ private String taskId; /** * 任務(wù)執行規則時(shí)間 */ private String expression; }
初始化三個(gè)任務(wù),分別為:
10秒執行一次(*/10 * * * * ?)
15秒執行一次(*/15 * * * * ?)
20秒執行一次(*/20 * * * * ?)
測試效果:
可以看到初始化的三個(gè)任務(wù)都在執行,并且是不用的線(xiàn)程在執行。
1、啟動(dòng)方式有兩種:
2、數據初始化
只需要給 List集合賦值并調用refreshTask()方法即可:
例如:從mysql讀取任務(wù)配置表的數據,調用refreshTask()方法。
3、如何動(dòng)態(tài)?
例如:我們有一張任務(wù)配置表,此時(shí)進(jìn)行分別新增一條或多條數據、刪除一條或多條數據、改一條數據,只需要完成以上任何一項操作后,重新調用一下refreshTask()方法即可。
怎么重新調用 refreshTask()方法:可以另外啟一個(gè)任務(wù)實(shí)時(shí)監控任務(wù)表的數據變化。
以上就是本文的全部?jì)热?,希望對大家的學(xué)習有所幫助,也希望大家多多支持腳本之家。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站