crontab

定时任务

Cron表达式

共七位,最少六位,表示如下,其中对英文缩写、特殊字符大小写不敏感

* * * * * * *
0-59 0-59 0-23 1-31 1-12/JAN-DEC 0-7/MON-SAT 1900 可选
, - * / , - * / , - * / , - * ? / L W C , - * / , - * ? / L C # , - * /

符号表示如下:

符号 说明
* 重复当前位置的周期,如1 * * * * ?表示每分钟的第一秒执行
, 用于指定多个值,如0 10,20,30 * * * ?表示每小时的10、20、30分执行
? 占位符
- 表示区间
/ a/b表示以 a 为起点步长为 b 的时间序列,如5/10 * * * * ?表示每分钟第5、15、25、35、45、55秒执行
L 月份最后一天或星期六,周位上 6L 表示月份的最后一个周五执行,L和 W 可以在日位中联合使用,LW 表示这个月最后一周的工作日
W 后边最近的工作日,1W 1日如果是周五,那就在4日执行,不可跨月,L和 W 可以在日位中联合使用,LW 表示这个月最后一周的工作日
# a#b 表示当月第 b 个星期 a,如 6#1 当月第一个星期五
C 关联日历计算结果

场景示例

1.Mac设置定时任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 确保存在文件 /etc/crontab,若没有则新建
sudo touch /etc/crontab
# 编辑crontab,写入定时脚本
vi /etc/crontab
# 生效定时脚本
crontab /etc/crontab
# 查看定时任务是否启动
sudo launchctl list | grep cron

# 状态查看
sudo /usr/sbin/cron start | restart | stop
# 查看已有任务列表
sudo crontab -l
# 编辑任务
sudo crontab -e
# 删除 定时脚本 文件
sudo crontab -r

我用terminal-notifier来实现terminal推送提醒功能,脚本如下:

1
2
3
4
# 每日凌晨更新homebrew
30 1 * * * * brew upadte
# 半小时起来走动
30 */1 * * * /usr/local/bin/terminal-notifier -title "休息,休息一下" -message "你再不站起来要变死肥宅了!" -ignoreDnD -group 1

2.Java中的定时任务需求

2.1 java.util.Timer (since JDK1.3)

执行时单线程,当抛出运行时异常时Timer 将停止所有的任务执行,会影响其他任务

1
2
3
4
5
6
7
8
9
10
11
12
13
public void demo() {
// 定义一个任务
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("Run timerTask:" + System.currentTimeMillis());
}
};
// 计时器
Timer timer = new Timer();
// 添加执行任务(延迟 1s 执行,每 3s 执行一次)
timer.schedule(timerTask, 1000, 3000);
}

2.2 java.util.concurrent.ScheduledExecutorService (since JDK1.5)

不影响其他任务

1
2
3
4
5
6
7
8
9
public void demo() {
// 创建任务队列
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(10); // 10 为线程数量
// 执行任务
scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println("Run Schedule:" + System.currentTimeMillis());
}, 1, 3, TimeUnit.SECONDS); // 1s 后开始执行,每 3s 执行一次
}

2.3 @Scheduled (based on Spring)

Spring自动加载和管理该定时任务

1
2
3
4
5
6
7
8
9
10
11
12
13
@SpringBootApplication
@EnableScheduling // 开启定时任务
public class DemoApplication {
...
}

@Component
public class TaskUtils {
@Scheduled(cron = “0 1 * * * ” )
public void doTask(){
System.out.println(“执行定时任务");
}
}

2.4 任务调度框架Quartz

在项目中使用需要引入quartz依赖,并且quartz有其独立的数据库,来支撑复杂的任务调度,详见官方文档