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。完全可以满足定时转储日志文件的需要。
log4go的精确定时程序(带自动延迟补偿)的更多相关文章
- 微信小程序—微信自动退款
微信小程序—微信自动退款 一.业务背景 微信自动退款串接基于酷客多小程序商城系统,为方便财务人员进行订单退款而开发,将酷客多小程序系统财务退款流程和微信退款系统打通.实现一个系统管理运营. 二.业务流 ...
- VC中基于 Windows 的精确定时[转]
在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...
- VC中基于 Windows 的精确定时
在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...
- Android应用程序的自动更新升级(自身升级、通过tomcat)(转)
Android应用程序的自动更新升级(自身升级.通过tomcat) http://blog.csdn.net/mu0206mu/article/details/7204746 刚入手android一个 ...
- 分析nuget源码,用nuget + nuget.server实现winform程序的自动更新
源起 (个人理解)包管理最开始应该是从java平台下的maven开始吧,因为java的开发大多数是基于开源组件开发的,一个开源包在使用时很可能要去依赖其他的开源包,而且必须是特定的版本才可以.以往在找 ...
- At.js – 用于 Web 应用程序的自动完成库
At.js 是一个自动完成库,用来实现自动完成提示,表情等,就像你在 Github 或 Twitter 上看到的一样.它支持 HTML5 contentEditable 元素.你可以听任何字符,而不仅 ...
- paip. 解决java程序不能自动退出
paip. 解决java程序不能自动退出 原因:有东西在运行,所以,不能自动退出.. 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址: ...
- WPF 设置程序开机自动运行(+注册表项)
#region 设置程序开机自动运行(+注册表项) RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Micr ...
- 使用Inno Setup 打包.NET程序,并自动安装.Net Framework
使用Inno Setup 打包.NET程序,并自动安装.Net Framework http://www.cnblogs.com/xiaogangqq123/archive/2012/03/19/24 ...
随机推荐
- 2017·iOS学习资料
我的两个想法更新了,欢迎新老司机出来槽点一下 star →[iOS·UIKit & Foundation框架-Annotations & Category注解工具类
- MPP 二、Greenplum数据加载
Loading external data into greenplum database table using different ways... Greenplum 有常规的COPY加载方法,有 ...
- 修改tomcat图标
页面上加入: 1 <link rel="shortcut icon" href="favicon.ico" type="image/x-icon ...
- Docker容器管理平台Humpback进阶-私有仓库
Docker私有仓库 在 Docker 中,当我们执行 docker pull xxx 的时候,可能会比较好奇,docker 会去哪儿查找并下载镜像呢? 它实际上是从 registry.hub.doc ...
- AppServ安装的一点小麻烦----
好久,没装AppServ了,今天安装过程顺利,但是Apache,服务开启不了,页面也不能访问. 刚开始以为是版本下载错误了,先后换了N个版本,都不行. 在网上搜的过程中,偶然发现,一句话:64位系统, ...
- Bash中的数学扩展
Bash只支持整数运算,不支持浮点运算.如果需要进行浮点运算,需要使用bc程序.Bash中的数学扩展有两种形式:$[ expression ]或$(( expression )) 例子:$echo $ ...
- java排序算法之冒泡排序
冒泡排序的基本思想即将一串数字进行由小到大进行排序 例如1,9,7,2,4,3,6,10,20,5 实现思路: 第一个数分别与接下来的数字做对比 第一次 1<9不变,再1<7不变,1&l ...
- 不再迷惑,无值和NULL值的转换
在关系型数据库的世界中,无值和NULL值的区别是什么?一直被这个问题困扰着,甚至在写TSQL脚本时,心有戚戚焉,害怕因为自己的一知半解,挖了坑,贻害后来人,于是,本着上下求索,不达通幽不罢休的决心(开 ...
- API 接口规范
整体规范建议采用RESTful 方式来实施. 1. 协议 API与用户的通信协议,总是使用HTTPs协议,确保交互数据的传输安全. 2. 域名 应该尽量将API部署在专用域名之下. https://a ...
- [css 实践篇] CSS box-orient
定义和用法 box-orient 属性规定框的子元素应该被水平或垂直排列. 提示:水平框中的子元素从左向右进行显示,而垂直框的子元素从上向下进行显示.不过,box-direction 和 box-or ...