SpringBoot(十三):springboot2.0.2定時任務

使用定義任務:

第一步:啓用定時任務
第二步:配置定時器資源等
第三步:定義定時任務並指定觸發規則web

1)啓動類啓用定時任務

在springboot入口類上添加註解@EnableScheduling便可。spring

@SpringBootApplication(scanBasePackages = {})
@MapperScan("com.dx.jobmonitor.mapper")
@EnableScheduling
public class App {
    private static final Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {
        logger.info("App start...");
        SpringApplication.run(App.class, args);
    }
}

2)配置定時任務資源等:

設置定時任務線程池大小:經過SchedulingConfigurer接口配置並行方式
當定時任務不少的時候,爲了提升任務執行效率,能夠採用並行方式執行定時任務,任務之間互不影響,只要實現SchedulingConfigurer接口就能夠。 數據庫

/**
 * 配置定時任務<br>
 * 1)當定時任務不少的時候,爲了提升任務執行效率,能夠採用並行方式執行定時任務,任務之間互不影響,只要實現SchedulingConfigurer接口就能夠。<br>
 * 2)這裏指定用3個線程來並行處理
 * **/
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.setScheduler(setTaskExecutors());
    }

    @Bean(destroyMethod = "shutdown")
    public Executor setTaskExecutors() {
        return Executors.newScheduledThreadPool(3);
    }
}


在並行執行的時候,建立線程池採用了newScheduledThreadPool這個線程池。
Executors框架中存在幾種線程池的建立線程池的採用的隊列是延遲隊列:express

  •     newCachedThreadPool() ,
  •     newFixedThreadPool(),
  •     newSingleThreadExecutor(),
  •     newScheduledThreadPool()。

newScheduledThreadPool() 線程池的特性是定時任務可以定時或者週期性的執行任務。springboot

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
}

其中線程池核心線程數是本身設定的,最大線程數是最大值。阻塞隊列是自定義的延遲隊列:DelayedWorkQueue()app

3)定義定時任務

定時任務1:框架

@Component
public class SchedulerTask {
    private int count=0;

    @Scheduled(cron="*/6 * * * * ?")
    private void process(){
        System.out.println("this is scheduler task runing  "+(count++));
    }
}

定時任務2:ide

從application.yml中讀取cron參數函數

@Component
public class Scheduler2Task {
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    @Scheduled("jobs.scheduled.cron")
    public void reportCurrentTime() {
        System.out.println("如今時間:" + dateFormat.format(new Date()));
    }
}

此時application.yml中配置信息以下:測試

jobs:
  scheduled:
    cron: 0/30 * * * * ?

參數說明:
  @Scheduled接受兩種定時的設置:

  1. 一種是cornexpression。
  2. 一種是Rate/Delay表達式(毫秒值):
  • @Scheduled(fixedRate = 6000):上一次開始執行時間點後每隔6秒執行一次。
  • @Scheduled(fixedDelay = 6000):上一次執行完畢時間點以後6秒再執行。
  • @Scheduled(initialDelay=1000, fixedRate=6000):第一次延遲1秒後執行,以後按fixedRate的規則每6秒執行一次。

動態修改scheduled的cron參數:

動態修改定時任務cron參數時:

  • 1)不須要重啓應用就能夠動態的改變Cron表達式的值
  • 2)不能使用@Scheduled(cron = 「${jobs.cron}」)實現
@Component
public class SpringDynamicCronTask implements SchedulingConfigurer {
    private static final Logger logger = LoggerFactory.getLogger(SpringDynamicCronTask.class);
    private static String cron = "0/5 * * * * ?";

    @Autowired
    private TaskDynamicCronService taskCronService;
    
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(() -> {
            // 任務邏輯
            logger.error("dynamicCronTask is running...");
        }, triggerContext -> {
            // 任務觸發,在這裏可修改任務的執行週期,由於每次調度都會執行這裏
            // 1)這裏能夠修改成從數據讀取cron
            // cron=taskCronService.getCron();
            CronTrigger cronTrigger = new CronTrigger(cron);
            return cronTrigger.nextExecutionTime(triggerContext);
        });
    }

    /**
    * 2) 供應用端調用動態修改cron參數方法
    * @Controller
    * @RequestMapping("/cron")")
    * public class CronController{
    *        @Autowired
    *        private SpringDynamicCronTask cronTask;
    *
    *         @PostMapping("/update")
    *        @ResponseBody
    *        public String update(String cron) {
    *            cronTask.setCron(cron);
    *        }
    * }
    */ 
    public void setCron(String cron) {
         this.cron=cron;
    }
}

動態設置cron參數經常使用方式包含兩種:

1)動態查詢並設置cron

定義CronTrigger時,從數據庫中動態查詢cron並設置

    @Autowired
    private TaskDynamicCronService taskCronService;
    
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(() -> {
            // 任務邏輯
            logger.error("dynamicCronTask is running...");
        }, triggerContext -> {
            cron=taskCronService.getCron();
            CronTrigger cronTrigger = new CronTrigger(cron);
            return cronTrigger.nextExecutionTime(triggerContext);
        });
    }

2)經過接口函數修改cron值

SpringDynamicCronTask 類,提供修改cron函數setCron()。

@Component
public class SpringDynamicCronTask implements SchedulingConfigurer {
    private static final Logger logger = LoggerFactory.getLogger(SpringDynamicCronTask.class);
    private static String cron = "0/5 * * * * ?";
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(() -> {
            // 任務邏輯
            logger.error("dynamicCronTask is running...");
        }, triggerContext -> {
            CronTrigger cronTrigger = new CronTrigger(cron);
            return cronTrigger.nextExecutionTime(triggerContext);
        });
    }

    /**
    * 供應用端調用動態修改cron參數方法
    */ 
    public void setCron(String cron) {
         this.cron=cron;
    }
}

應用端調用:

@Controller
@RequestMapping("/cron")")
public class CronController{
        @Autowired
        private SpringDynamicCronTask cronTask;

        @PostMapping("/update")
        @ResponseBody
        public String update(String cron) {
           cronTask.setCron(cron);
        }
}

多定時任務管理

定義多定時任務管理類

class BatchTaskSchedule {
    private ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
    private ScheduledFuture<?> future;
    private Integer key;

    public BatchTaskSchedule(Integer key) {
        this.key = key;
    }

    public void start() {
        executor.setPoolSize(1);
        executor.setThreadNamePrefix("taskExecutor-");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        // 必須得先初始化,才能使用
        executor.initialize();
        future = executor.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("[" + Thread.currentThread().getName() + "-" + key + "]Hello "
                        + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            }
        }, new CronTrigger("0/15 * * * * ?"));
    }

    public void restart() {
        // 先中止,在開啓.
        stop();
        start();
    }

    public void stop() {
        if (future != null) {
            future.cancel(true);
        }
    }
}

使用測試示例:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = { App.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CommonTest {
    // 定時任務存儲集合:當須要中止、重啓任務時,能夠從該集合中獲取待操做任務。
    private static Map<Integer, BatchTaskSchedule> taskBack = new HashMap<Integer, BatchTaskSchedule>();

    @Test
    public void test() {
        for (int i = 0; i < 2; i++) {
            // 建立定時任務
            BatchTaskSchedule taskScheduled = new BatchTaskSchedule(i);
            taskScheduled.start();
            taskBack.put(i, taskScheduled);
        }

        try {
            Thread.sleep(1 * 60 * 1000);
            // 中止掉某個任務
            taskBack.get(0).stop();
            Thread.sleep(1 * 60 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
相關文章
相關標籤/搜索