- Created by 郭强, last modified on Jan 06, 2023
基本使用
package main import ( "context" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gcron" "github.com/gogf/gf/v2/os/gctx" "time" ) func main() { var ( err error ctx = gctx.New() ) _, err = gcron.Add(ctx, "* * * * * *", func(ctx context.Context) { g.Log().Print(ctx, "Every second") }, "MySecondCronJob") if err != nil { panic(err) } _, err = gcron.Add(ctx, "0 30 * * * *", func(ctx context.Context) { g.Log().Print(ctx, "Every hour on the half hour") }) if err != nil { panic(err) } _, err = gcron.Add(ctx, "@hourly", func(ctx context.Context) { g.Log().Print(ctx, "Every hour") }) if err != nil { panic(err) } _, err = gcron.Add(ctx, "@every 1h30m", func(ctx context.Context) { g.Log().Print(ctx, "Every hour thirty") }) if err != nil { panic(err) } g.Dump(gcron.Entries()) time.Sleep(3 * time.Second) g.Log().Print(ctx, `stop cronjob "MySecondCronJob"`) gcron.Stop("MySecondCronJob") time.Sleep(3 * time.Second) g.Log().Print(ctx, `start cronjob "MySecondCronJob"`) gcron.Start("MySecondCronJob") time.Sleep(3 * time.Second) }
执行后,输出结果为:
[ { Name: "MySecondCronJob", Job: 0x14077e0, Time: "2021-11-14 12:13:53.445132 +0800 CST m=+0.006167069", }, { Name: "cron-1", Job: 0x14078a0, Time: "2021-11-14 12:13:53.44515 +0800 CST m=+0.006185688", }, { Name: "cron-2", Job: 0x1407960, Time: "2021-11-14 12:13:53.445161 +0800 CST m=+0.006196483", }, { Name: "cron-3", Job: 0x1407a20, Time: "2021-11-14 12:13:53.445218 +0800 CST m=+0.006252937", }, ] 2021-11-14 12:13:54.442 {189cwi9ngk0cfp7l8gcwciw100sr9cuu} Every second 2021-11-14 12:13:55.441 {189cwi9ngk0cfp7l8gcwciw100sr9cuu} Every second 2021-11-14 12:13:56.440 {189cwi9ngk0cfp7l8gcwciw100sr9cuu} Every second 2021-11-14 12:13:56.445 {189cwi9ngk0cfp7l8gcwciw100sr9cuu} stop cronjob "MySecondCronJob" 2021-11-14 12:13:59.445 {189cwi9ngk0cfp7l8gcwciw100sr9cuu} start cronjob "MySecondCronJob" 2021-11-14 12:14:00.443 {189cwi9ngk0cfp7l8gcwciw100sr9cuu} Every second 2021-11-14 12:14:01.442 {189cwi9ngk0cfp7l8gcwciw100sr9cuu} Every second 2021-11-14 12:14:02.443 {189cwi9ngk0cfp7l8gcwciw100sr9cuu} Every second
单例定时任务
单例定时任务,即同时只能有一个该任务正在运行。当第二个相同的定时任务触发执行时,如果发现已有该任务正在执行,第二个任务将会退出不执行,定时器将会继续等待下一次定时任务的触发检测,以此类推。可以使用AddSingleton
添加单例定时任务。
package main import ( "context" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gcron" "github.com/gogf/gf/v2/os/gctx" "time" ) func main() { var ( err error ctx = gctx.New() ) _, err = gcron.AddSingleton(ctx, "* * * * * *", func(ctx context.Context) { g.Log().Print(ctx, "doing") time.Sleep(2 * time.Second) }) if err != nil { panic(err) } select {} }
执行后,输出结果为:
2021-11-14 12:16:54.073 {189cwi9nmm0cfp7niz319fc100zrw0ig} doing 2021-11-14 12:16:57.072 {189cwi9nmm0cfp7niz319fc100zrw0ig} doing 2021-11-14 12:17:00.072 {189cwi9nmm0cfp7niz319fc100zrw0ig} doing 2021-11-14 12:17:03.071 {189cwi9nmm0cfp7niz319fc100zrw0ig} doing 2021-11-14 12:17:06.072 {189cwi9nmm0cfp7niz319fc100zrw0ig} doing 2021-11-14 12:17:09.072 {189cwi9nmm0cfp7niz319fc100zrw0ig} doing ...
单次定时任务
单次定时任务,AddOnce
方法用于添加只运行一次的定时任务,当运行一次数后该定时任务自动销毁,Size
方法可以查看运行状态,相关方法:
func main() { var ( ctx = gctx.New() ) cron := gcron.New() array := garray.New(true) cron.AddOnce(ctx, "@every 2s", func(ctx context.Context) { array.Append(1) }) fmt.Println(cron.Size(),array.Len()) time.Sleep(3000 * time.Millisecond) fmt.Println(cron.Size(),array.Len()) }
执行后,输出结果为:
1 0 0 1
指定次数的定时任务
指定次数的定时任务,AddTimes
方法用于添加运行指定次数的定时任务,当运行times
次数后该定时任务自动销毁,Size
方法可以查看运行状态,相关方法:
func main() { var ( ctx = gctx.New() ) cron := gcron.New() array := garray.New(true) cron.AddTimes(ctx, "@every 2s", 2,func(ctx context.Context) { array.Append(1) }) fmt.Println(cron.Size(), array.Len()) time.Sleep(3000 * time.Millisecond) fmt.Println(cron.Size(), array.Len()) time.Sleep(3000 * time.Millisecond) fmt.Println(cron.Size(), array.Len()) }
执行后,输出结果为:
1 0 1 1 0 2
获取所有注册的定时任务信息
获取所有注册的定时任务信息,Entries
方法用于获取当前所有已注册的定时任务信息,以切片的形式返回(按注册时间asc
排序),相关方法:
func main() { var ( ctx = gctx.New() ) cron := gcron.New() array := garray.New(true) cron.AddTimes(ctx, "@every 1s", 2,func(ctx context.Context) { array.Append(1) },"cron1") cron.AddOnce(ctx, "@every 1s",func(ctx context.Context) { array.Append(1) },"cron2") entries := cron.Entries() for k, v := range entries{ fmt.Println(k,v.Name,v.Time) } time.Sleep(3000 * time.Millisecond) fmt.Println(array.Len()) }
执行后,输出结果为:
0 cron2 2022-02-09 10:11:47.2421345 +0800 CST m=+0.159116501 1 cron1 2022-02-09 10:11:47.2421345 +0800 CST m=+0.159116501 3
任务搜索
Search
搜索返回具有指定“名称”的计划任务。(返回定时任务*Entry
对象指针),如果找不到,则返回nil。相关方法:
func main() { var ( ctx = gctx.New() ) cron := gcron.New() array := garray.New(true) cron.AddTimes(ctx, "@every 1s", 2,func(ctx context.Context) { array.Append(1) },"cron1") cron.AddOnce(ctx, "@every 1s",func(ctx context.Context) { array.Append(1) },"cron2") search := cron.Search("cron2") g.Log().Print(ctx, search) time.Sleep(3000 * time.Millisecond) fmt.Println(array.Len()) // Output: // 3 }
执行后,输出结果为:
2022-02-09 10:52:30.011 {18a909957cfed11680c1b145da1ef096} {"Name":"cron2","Time":"2022-02-09T10:52:29.9972842+08:00"}
任务停止
Stop
方法用于停止定时任务(Stop
会停止但不会删除), 可通过name
参数指定需要停止的任务名称,如果没有指定name
,它将停止整个cron
。相关方法:
func main() { var ( ctx = gctx.New() ) cron := gcron.New() array := garray.New(true) cron.AddTimes(ctx, "@every 2s", 1,func(ctx context.Context) { array.Append(1) },"cron1") cron.AddOnce(ctx, "@every 2s",func(ctx context.Context) { array.Append(1) },"cron2") fmt.Println(array.Len(),cron.Size()) cron.Stop("cron2") fmt.Println(array.Len(),cron.Size()) time.Sleep(3000 * time.Millisecond) fmt.Println(array.Len(),cron.Size()) // Output: // 1 // 1 }
执行后,输出结果为:
0 2 0 2 1 1
任务停止并删除
Remove
方法用于根据名称name
删除定时任务(停止并删除);相关方法:
func main() { var ( ctx = gctx.New() ) cron := gcron.New() array := garray.New(true) cron.AddTimes(ctx, "@every 2s", 1,func(ctx context.Context) { array.Append(1) },"cron1") cron.AddOnce(ctx, "@every 2s",func(ctx context.Context) { array.Append(1) },"cron2") fmt.Println(array.Len(),cron.Size()) cron.Remove("cron2") fmt.Println(array.Len(),cron.Size()) time.Sleep(3000 * time.Millisecond) fmt.Println(array.Len(),cron.Size()) // Output: // 0 2 // 0 1 // 1 0 }
执行后,输出结果为:
0 2 0 1 1 0
任务启动
Start
方法用于启动定时任务(Add
后自动启动定时任务), 可通过name
参数指定需要启动的任务名称。如果没有指定name
,它将启动整个cron
。相关方法:
func main() { var ( ctx = gctx.New() ) cron := gcron.New() array := garray.New(true) cron.AddOnce(ctx, "@every 2s",func(ctx context.Context) { array.Append(1) },"cron2") cron.Stop("cron2") time.Sleep(3000 * time.Millisecond) fmt.Println(array.Len(),cron.Size()) cron.Start("cron2") time.Sleep(3000 * time.Millisecond) fmt.Println(array.Len(),cron.Size()) // Output: // 0 1 // 1 0 }
执行后,输出结果为:
0 1 1 0
Content Menu
- No labels
15 Comments
杨阳
请问如何在添加定时任务时就立即执行一次,并且和后续的定时执行一起受单例约束
糖水不加糖
gcron.Add后自己在代码后面直接写一次执行一次对应的逻辑方法不就完事了
杨阳
我的应用场景是这样的,10分钟执行一次定时任务,但任务有可能会执行15分钟以上,要保证同一时间只有一个该任务在运行。
我用gcron.AddSingleton保证该任务同一时间只有一个运行,但是第一次,如果是gcron后在自己在代码后面直接写一次执行一次对应的逻辑,那么这次执行一旦超过10分钟,就会出现同时两个该任务实例在运行的情况。
糖水不加糖
做任务状态就好了.对于某一个任务,在启动任务是将该任务状态置为进行中,当任务执行完成时状态改为未运行(修改状态记得加锁).第二次任务开始时先判该任务当前状态即可.至于要强行终止第一次任务还是第二次任务不启动就看你业务需求了.
杨阳
谢谢,看网上说java的cron好像可以支持立即执行一次,所以想问问gcron是否也支持
刘羽禅
用gf的gcmd和xxljob任务调度平台结合到一起, 任务添加后 点击 立即执行一次就行了
suyar
您好,我是go语言的初学者,我想请问下比如定时任务的初始化、比如队列的初始化,一些前置配置应该写在哪里?虽然我看完了《框架设计》章节,但是并没有发现类似的说明。
比如我是应该写在 `main.go`:
还是应该放在 cmd 里面:
我知道这东西没有银弹,但是能不能给我一点点您的建议,感激不尽!
hui
个人感觉从功能上来说,放到
main.go
和cmd
都可以,没有严格的区别,看团队的喜好,不用太纠结。con
为什么上面“基本使用”里的代码原封不动的复制到本地来运行跑报错呢? panic: reflect: call of reflect.Value.Type on zero Value
大耳朵牛爷爷
郭强
基本使用案例误导人了,可以优化下: 缺少
lesama
你好,请问在单例定时任务中,如果A任务检测到B任务正在进行,那么A任务是直接退出了,还是进入了阻塞态呢?
郭强
直接退出。
lesama
谢谢大佬
don178
这些方法是并发安全的吗?
liewkaitsan
我在定时任务里面连接了远程的ssh客户端,有时候连接不上ssh会直接退出这个程序,导致我别的任务都没法执行了。我并没有手动panic都是输出error的形式