1 回答
TA贡献1862条经验 获得超7个赞
您的实现与 Go 中的计划作业/任务非常相似。有一些类似 cron 的库可以让您更好地控制任务,但在大多数情况下,带有循环的简单 goroutine 就足够了。
以下是根据您的需求增加复杂性的更多示例:
永远运行一个任务,每次运行之间等待 5 秒。无法停止并且不考虑任务的运行时间。这是最简单的形式,也是最常见的形式。
go func() {
for {
task()
<-time.After(5 * time.Second)
}
}()
与以前相同,只是现在有一个通道可以在我们想要的时候停止任务。虽然您的实现允许您通过该方法停止任务Stop(),但 goroutine 将保持打开状态,因为通道永远不会关闭(因此会泄漏内存)。
// Includes a channel to stop the task if needed.
quit := make(chan bool, 1)
go func() {
task()
for {
select {
case <-quit:
return
case <-time.After(5 * time.Second):
task()
}
}
}()
// To stop the task
quit <- true
这是三个解决方案中最强大的解决方案。任务可以随时停止,并且它还会考虑任务在等待再次运行时所花费的时间。在前面的示例中,如果任务运行时间为 1 秒,而您又等待 5 秒,则相对于任务启动时的时间间隔实际上是 6 秒。
该解决方案实际上仅适用于运行时间非常长的任务,或者如果您的任务以恒定的时间间隔运行至关重要。如果任务必须以恒定的时间间隔运行,那么您需要考虑到time.After()至少会等待您提供的持续时间的事实——如果 CPU 忙于其他进程/goroutines,它最终可能会等待稍长的时间。
// Calls `fn` and then waits so the total elapsed time is `interval`
func runAndWait(interval time.Duration, fn func()) {
earlier := time.Now()
fn()
diff := time.Now().Sub(earlier)
<-time.After(interval - diff)
}
quit := make(chan bool, 1)
go func() {
// The total time to run one iteration of the task
interval := 5 * time.Second
for {
select {
case <-quit:
return
default:
runAndWait(interval, task)
}
}
}()
- 1 回答
- 0 关注
- 97 浏览
添加回答
举报