计划任务的Spring实现与手动实现
手写计划任务当然比不过简单又好用的SpringScheduled
使用Spring Scheduled的计划任务
关键方法
- 计算下一次匹配CRON表达式的时间
new CronSequenceGenerator("1 1 0 1 * ?").next(new Date());
- 该方法用于计算下一次运行的到现在时间的时间差
org.springframework.scheduling.concurrent.ReschedulingRunnable#schedule();
实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
@Component @EnableScheduling public class ScheduleConfig {
public static final String CRON_EXPRESSION = "0 0 0 1 * ?";
@Scheduled(cron = CRON_EXPRESSION, zone = "Asia/Shanghai") public void generateFormJob() { System.out.println(new Date().toString() + " >>计划任务执行...."); } }
|
自己写的计划任务
思路
- 使用一个阻塞队列
- 使用一个线程去消费队列
- 使用一个线程在计算
现在到下次执行时间的时间差
并睡到下次执行时间将Runable放入队列中消费
实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
private LinkedBlockingQueue<runnable> queue = new LinkedBlockingQueue<>();
private Runnable task = () -> { System.out.println(new Date().toString() + " >>计划任务执行...."); };
@SuppressWarnings({"all", "AlibabaAvoidManuallyCreateThread"}) public ScheduleConfig() { Thread take = new Thread(() -> { try { while (true) { Runnable runnable = runnable = queue.take(); runnable.run(); } } catch (InterruptedException ignored) {} }); take.setDaemon(true); take.setName("schedule-take");
Thread put = new Thread(() -> { Runnable runnable = null; try { while (true) { Date next = new CronSequenceGenerator(CRON_EXPRESSION).next(new Date()); Thread.sleep(next.getTime() - System.currentTimeMillis()); queue.put(task); } } catch (InterruptedException ignored) {} }); put.setDaemon(true); put.setName("schedule-put");
take.start(); put.start(); }
|