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


    程序设计目标是在程序启动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。完全可以满足定时转储日志文件的需要。

  • 相关阅读:
    「UVA12293」 Box Game
    「CF803C」 Maximal GCD
    「CF525D」Arthur and Walls
    「CF442C」 Artem and Array
    LeetCode lcci 16.03 交点
    LeetCode 1305 两棵二叉搜索树中的所有元素
    LeetCode 1040 移动石子直到连续 II
    LeetCode 664 奇怪的打印机
    iOS UIPageViewController系统方法崩溃修复
    LeetCode 334 递增的三元子序列
  • 原文地址:https://www.cnblogs.com/ccpaging/p/7203431.html
Copyright © 2020-2023  润新知