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

log4go的精确定时程序(带自动延迟补偿)的更多相关文章

  1. 微信小程序—微信自动退款

    微信小程序—微信自动退款 一.业务背景 微信自动退款串接基于酷客多小程序商城系统,为方便财务人员进行订单退款而开发,将酷客多小程序系统财务退款流程和微信退款系统打通.实现一个系统管理运营. 二.业务流 ...

  2. VC中基于 Windows 的精确定时[转]

    在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...

  3. VC中基于 Windows 的精确定时

    在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...

  4. Android应用程序的自动更新升级(自身升级、通过tomcat)(转)

    Android应用程序的自动更新升级(自身升级.通过tomcat) http://blog.csdn.net/mu0206mu/article/details/7204746 刚入手android一个 ...

  5. 分析nuget源码,用nuget + nuget.server实现winform程序的自动更新

    源起 (个人理解)包管理最开始应该是从java平台下的maven开始吧,因为java的开发大多数是基于开源组件开发的,一个开源包在使用时很可能要去依赖其他的开源包,而且必须是特定的版本才可以.以往在找 ...

  6. At.js – 用于 Web 应用程序的自动完成库

    At.js 是一个自动完成库,用来实现自动完成提示,表情等,就像你在 Github 或 Twitter 上看到的一样.它支持 HTML5 contentEditable 元素.你可以听任何字符,而不仅 ...

  7. paip. 解决java程序不能自动退出

    paip. 解决java程序不能自动退出 原因:有东西在运行,所以,不能自动退出.. 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址: ...

  8. WPF 设置程序开机自动运行(+注册表项)

    #region 设置程序开机自动运行(+注册表项) RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Micr ...

  9. 使用Inno Setup 打包.NET程序,并自动安装.Net Framework

    使用Inno Setup 打包.NET程序,并自动安装.Net Framework http://www.cnblogs.com/xiaogangqq123/archive/2012/03/19/24 ...

随机推荐

  1. javascript基础-事件1

    原理 事件分两种.第一种浏览器事件,由浏览器抛出事件,它是人机交互的基础:第二种自定义事件,由程序员抛出事件,它是模拟事件流程.两者都是为了完成数据的传递. 浏览器事件 机制 冒泡和捕获两种机制.因I ...

  2. 红包项目总结---MVC版

    起因: 针对传统版的明显缺陷做优化.主要是提升可维护性. 效果  线上:  未发布 线下:http://10.27.5.1/svn/FED/code/hongbao/year-end   hb-fac ...

  3. Assert与内存泄漏

    以前知道C/C++有assert之后,我想知道assert会不会造成内存泄漏,于是我做了一个测试: #include <iostream> #include <fstream> ...

  4. 分享几个python小脚本

    by 梁凯 今天我想给大家分享几个python脚本,分别是: 1.公司访问外网认证脚本(最初有同事写过,我优化了一下). 2.统计周报系统所有同事的最近一篇周报. 3.统计测试技术分享里指定一个月所有 ...

  5. Expression 转化为sql(三) --自定义函数

    SQL 语句有很多函数如len(),now()等等.如何来生成这些函数.最近研究也写办法共大家参考. 一.首先建立一个建一个扩展类,控制只能允许这些函数出现,如果出现其他函数就直接报异常. publi ...

  6. Canvas学习系列二:Canvas的坐标系统

    上一章内容中我们对canvas元素有了一个初步的认识,在接下来的章节中我们会慢慢学习canvas中图形的绘制:但是在绘制之前我们先来看看canvas中的坐标系统,因为这样我们才能知道绘制的图形放在什么 ...

  7. redis bitcount variable-precision swar算法

    花了不到一周的时间看完了一本reids设计与实现的书,感觉整体的设计有些地方的确很巧妙,各个结构之间联系的非常紧密,但是很简单,逻辑性的没有太多,但是学到了一个bitcount计数1的方法比较巧妙,记 ...

  8. java面试基础题(三)

    程序员面试之九阴真经 谈谈final, finally, finalize的区别: final:::修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此 ...

  9. 活动页怎么切图photoshop

    一 切固定大小的单个图片 1.用pc打开图像 2.按ctrl+A(全选) 3.点击 选择 ->变换选区 ->拉参考线(把参考线放到最中央)->按回车 ->ctrl+d(取消全选 ...

  10. 关于Handler的理解,子线程不能更新UI的纠正和回调的思考

    开发Android这么久了,总会听到有人说:主线程不能访问网络,子线程不能更新UI.Android的主线程的确不能长时间阻塞,但是子线程为什么不能更新UI呢?今天把这些东西整理,顺便在子线程更新UI. ...