log4go的精确定时程序(带自动延迟补偿)

本文介绍了一个Go语言程序设计案例,旨在解决定时任务的精确执行问题。初始方案使用了简单的定时器,但存在累积误差的问题。通过引入额外的时间变量并调整定时器设置方式,实现了更高的时间精度,满足了日志转储等场景的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序设计目标是在程序启动10秒后执行某个任务,例如日志转储(rotate),以后每隔15秒执行一次。

初次的设计

package main

import (
    "time"
    "fmt"
)

func main() {
    timer := time.NewTimer(10 * time.Second)
    fmt.Println(time.Now())
    for {
        select {
        case <-timer.C:
            fmt.Println(time.Now())
            time.Sleep(1 * time.Second)
            timer.Reset(15 * time.Second)
        }
    }
}

显然,在设置下一个定时(timer.Reset(15 * time.Second))之前,多少都会消耗一点时间,即使是毫秒级的延迟,也一定会产生累计误差。
为了使问题更明显,在程序中增加了一秒的 Sleep。测试结果如下:

2017-07-18 23:16:24.791623 +0800 CST
2017-07-18 23:16:34.7917567 +0800 CST
2017-07-18 23:16:50.7920782 +0800 CST
2017-07-18 23:17:06.7929373 +0800 CST
2017-07-18 23:17:22.7944063 +0800 CST
2017-07-18 23:17:38.7951302 +0800 CST
2017-07-18 23:17:54.7968096 +0800 CST
2017-07-18 23:18:10.7985468 +0800 CST
2017-07-18 23:18:26.7993588 +0800 CST
2017-07-18 23:18:42.7996568 +0800 CST
2017-07-18 23:18:58.8008621 +0800 CST

改进后的程序

package main

import (
    "time"
    "fmt"
)

func main() {
    next := time.Now().Add(10 * time.Second)
    timer := time.NewTimer(next.Sub(time.Now()))
    fmt.Println(time.Now())
    for {
        select {
        case <-timer.C:
            fmt.Println(time.Now())
            time.Sleep(1 * time.Second)
            next = next.Add(15 * time.Second)
            timer.Reset(next.Sub(time.Now()))
        }
    }
}

简单说就是增加了一个时间变量 next,在设置定时器之前,通过计算获得下一次任务的执行时间。
而定时器用 next - Now() 来设置。测试结果如下:

2017-07-18 23:16:20.2456695 +0800 CST
2017-07-18 23:16:30.2466397 +0800 CST
2017-07-18 23:16:45.2457191 +0800 CST
2017-07-18 23:17:00.2458328 +0800 CST
2017-07-18 23:17:15.2451861 +0800 CST
2017-07-18 23:17:30.2452624 +0800 CST
2017-07-18 23:17:45.2468138 +0800 CST
2017-07-18 23:18:00.245947 +0800 CST

从以上结果看,精度可控制在 ± 2ms。完全可以满足定时转储日志文件的需要。

转载于:https://www.cnblogs.com/ccpaging/p/7203431.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值