Golang——Cron 定时任务
开门见山写一个
package main import (
"fmt"
"github.com/robfig/cron"
"log"
"strings"
"time"
) func CronTask() {
log.Println("******** ******* *******")
} func CronTest() {
log.Println("Starting Cron...") c := cron.New()
c.AddFunc("* * * * * *", CronTask) //2 * * * * *, 2 表示每分钟的第2s执行一次
c.Start() t1 := time.NewTimer(time.Second * ) // ?time.Second * 10 啥意思? *100行吗?
for {
select {
case <-t1.C:
fmt.Println("Time now:", time.Now().Format("2006-01-02 15:04:05")) // 为何要专门制定这个时间
t1.Reset(time.Second * )
}
}
} func main() {
fmt.Println(strings.Repeat("START ", ))
CronTest()
fmt.Println(strings.Repeat("END ", ))
}
核心的定时器代码就3行
c := cron.New()
c.AddFunc("* * * * * *", CronTask)
c.Start()
那后面那些代码时作甚的?
一开始看到示例代码时,有个疑惑,如代码中注释
t1 := time.NewTimer(time.Second * 10)
这里time.Second*10是干啥的? 是否可以写成*100呢, 改了后原来是可以的,那更疑惑了既然都行为啥还要写个这个?
还有后面的for-select-case也是一脸懵逼~~~~
运行代码,从结果反推下原理吧,一次执行结果
START START START START START START START START START START START START START START START
// :: Starting Cron...
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
Time now: -- ::
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
Time now: -- ::
// :: ******** ******* *******
以上是运行的片段,有两大发现
- 有START START START。。。没有END END END 。。。。:说明了代码在执行时阻塞在定时器里,定时器没有执行完,永远不会执行END
- Time now打出来的间隔正好是10s
哦,原来time.NewTimer是个定时器,当这个时间间隔完了后再重新打开一个。for-select-case 这一块目的是阻塞流程,不让程序结束。 理解对吗
如果是这样,去掉for-select-case 执行第一个定时器时也可以停10s,是这样吗?试验下:屏蔽掉for-select-case, 输出
START START START START START START START START START START START START START START START
// :: Starting Cron...
END END END END END END END END END END END END END END END
打脸了,看来阻塞主要靠for-select-case实现,那原理是什么呢?
去掉t1.Reset效果咋样呢?
t1 := time.NewTimer(time.Second * ) // ?time.Second * 10 啥意思? *100行吗?
for {
fmt.Println("hihihihi")
select {
case <-t1.C:
fmt.Println("hello")
}
}
输出
START START START START START START START START START START START START START START START
// :: Starting Cron...
hihihihi
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
hello
hihihihi
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
// :: ******** ******* *******
更蒙了,去掉reset, 运行完第一个定时器10s, 非但没听,还直接执行起来了,没停了
for 循环里的print不是刷刷的一大片,而是和case命中时一期打,看来是时候了解下select-case的原理了
select case
按惯例先上个例子
package main import (
"fmt"
"strings"
) func SelectTest() {
intChan := make(chan int, )
stringChan := make(chan string, )
intChan <-
stringChan <- "hello" select {
case value := <-intChan:
fmt.Println(value)
case value := <- stringChan:
fmt.Println(value)
}
} func main() {
fmt.Println(strings.Repeat("START ", ))
SelectTest()
fmt.Println(strings.Repeat("END ", ))
}
执行多次可以看到,输出的结果是 123456、"hello"不定
select 语法
每个case都必须是个通信
如果一个通信可进行它就执行,其他被忽略
如果有多个case可执行,就会随机的选择一个执行
如果没有case可执行,如果如果有default,执行default语句;否则就阻塞,直到有某个通信可行
这里还是有很多问题,单开一节弄清楚 select语句
再回到一开始的定时任务
回归正题,定时原理解析
t1 := time.NewTimer(time.Second * )
for {
select {
case <-t1.C:
fmt.Println("Time now:", time.Now().Format("2006-01-02 15:04:05"))
t1.Reset(time.Second * )
}
}
- 生成一个定时器t1, 执行for循环,一开始定时时间(10s)未到, 也没有阻塞任务,它就阻塞在case中;
- 定时时间到了,则执行case中语句;
- 然后又重新恢复定时时长
- 重新走for循环,还是重复上面的故事
上面代码中尝试把case中的t1.Reset去掉,结果也是定时任务不同的执行,原因是执行case中的语句后,接着执行for循环,由于没有新通信过来(case语句永远无法满足),同时没有default语句,所以同样可以阻塞再次。
相比在case中t1 Reset, t1 Reset更灵活些,因为可以再每次重新满足case时做一些灵活的操作,比如跳出循环,做一些统计打印等。
Golang——Cron 定时任务的更多相关文章
- Golang cron 定时任务使用
1.cron 表达式的基本格式 用过 linux 的应该对 cron 有所了解.linux 中可以通过 crontab -e 来配置定时任务.不过,linux 中的 cron 只能精确到分钟.而我们这 ...
- golang的定时任务
golang的定时任务使用的是cron这个包来解决的 官方文档地址:https://godoc.org/github.com/robfig/cron cron包的基础知识 字段名 是否必须 允许的值 ...
- Go cron定时任务的用法
cron是什么 cron的意思就是:计划任务,说白了就是定时任务.我和系统约个时间,你在几点几分几秒或者每隔几分钟跑一个任务(job),就那么简单. cron表达式 cron表达式是一个好东西,这个东 ...
- 使用 cron 定时任务实现 war 自动化发布
autoRelease.sh #!/bin/sh /home/tomcat/bin/shutdown.sh echo "tomcat stoped" cd /home/tomcat ...
- cron定时任务介绍
什么是cron? Cron是linux系统中用来定期执行或指定程序任务的一种服务或软件.与它相关的有两个工具:crond 和 crontab.crond 就是 cron 在系统内的宿主程序,cront ...
- linux ,cron定时任务 备份mysql数据库
cron 定时任务执行备份脚本文件 backup.sh #!/bin/bash USER="root" PASSWORD="xxxxx" DATABASE=&q ...
- 珠峰培训node 珠峰爬虫| cron 定时任务
1.cron 定时任务 CronJob var CronJob = require('cron').CronJob; // 秒 分钟 时 天
- Cron定时任务应用到Thinkphp – 贤生博客
Cron定时任务应用到Thinkphp 安装crontab: yum install crontabs 关于cron的一些命令: /sbin/service crond start //启动服务 /s ...
- linux下的cron定时任务知识梳理
1 cron定时任务 1.1 cron介绍 为什么需要cron定时任务? 1)cron服务在安装完Linux系统后就默认就存在,主要用来定期执行命令或定期执行指定的应用程序; 2)cron服务默认情况 ...
随机推荐
- 2019NYIST计科第七次周赛总结
2019NYIST计科第七次周赛总结 文章目录 2019NYIST计科第七次周赛总结 [秤取物体重量( 二进制枚举法)](https://blog.csdn.net/qq_34261446/artic ...
- 为什么我建议每个开发人员都需要学Python?
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://dzone.com/articles/10-reasons-why-every-d ...
- MFC 工具栏ToolBar
一.创建工具栏 1.在MFC工程,找到“资源视图”界面,右键添加资源,选择Toolbar,点击新建: 2.修改工具条属性: 3.添加工具: 新建ToolBar后,会自动生成一个工具,编辑ID后,工具条 ...
- 本地代码上传到git仓库(github)
准备:拥有自己的github账号:电脑上安装了git; 1.进入github,进入仓库点击NEW(新建仓库) 2.新建仓库 Repository name :仓库名称: Description (op ...
- python3的subprocess的各个方法的区别(-)
subprocess(python3.7) subprocess 主要是为了替换一下的模块函数,允许你执行一些命令,并获取返回的状态码和 输入,输出和错误信息. os.systemos.spawn* ...
- Java第十天,多态
多态 一.多态的定义: 一个对象拥有多种形态,这就是对象的多态性.也就是说多态针对的是对象.多态的前提是接口和继承(C++中实行多继承,不存在接口). 二.多态在代码中的形式: 父类 对象名 = ne ...
- ENVI 安装
本文转自https://jingyan.baidu.com/article/2d5afd69d50e9585a2e28e37.html 但对该文有所补充,建议看本文,本文更详细. ENVI5.3安装 ...
- 数据结构和算法(Golang实现)(2)简单入门Golang-包、变量和函数
包.变量和函数 一.举个例子 现在我们来建立一个完整的程序main.go: // Golang程序入口的包名必须为 main package main // import "golang&q ...
- Java成长记录第二集--基础重点
第一篇写的博客给自己的学习路线立了个flag后,感觉现在学习的积极性大增,这也离不开那几位老铁们的互相鼓励.废话不多说,现在给出自己总结的Java基础部分所要重点注意的内容,对以后的开发工作也是很常用 ...
- AJ学IOS(21)UIApplication设置程序图标右上⾓红⾊数字_联⺴指⽰器等
AJ分享,必须精品 效果简介 UIApplication的运用,有很多相如:进⾏行⼀一些应⽤用级别的操作等等,打开网页,打开电话拨号和信息等.. 什么是UIApplication ● UIApplic ...