- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章golang time包下定时器的实现方法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
golang time包 。
和python一样,golang时间处理还是比较方便的,以下介绍了golang 时间日期,相关包 "time"的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍.
时间戳 。
当前时间戳 。
1
2
|
fmt.Println(time.Now().Unix())
# 1389058332
|
str格式化时间 。
当前格式化时间 。
1
2
|
fmt.Println(time.Now().
Format
(
"2006-01-02 15:04:05"
))
/
/
这是个奇葩,必须是这个时间点, 据说是go诞生之日, 记忆方法:
6
-
1
-
2
-
3
-
4
-
5
# 2014-01-07 09:42:20
|
时间戳转str格式化时间 。
1
2
3
|
str_time :
=
time.Unix(
1389058332
,
0
).
Format
(
"2006-01-02 15:04:05"
)
fmt.Println(str_time)
# 2014-01-07 09:32:12
|
str格式化时间转时间戳 。
这个比较麻烦 。
1
2
3
4
|
the_time := time.Date(2014, 1, 7, 5, 50, 4, 0, time.Local)
unix_time := the_time.Unix()
fmt.Println(unix_time)
# 389045004
|
还有一种方法,使用time.Parse 。
1
2
3
4
5
6
|
the_time, err := time.Parse("2006-01-02 15:04:05", "2014-01-08 09:04:41")
if err == nil {
unix_time := the_time.Unix()
fmt.Println(unix_time)
}
# 1389171881
|
以上简单介绍了golang中time包的相关内容,下面开始本文的正文.
引言 。
这篇文章简单的介绍下golang time 包下定时器的实现,说道定时器,在我们开发过程中很常用,由于使用的场景不同,所以对定时器实际的实现也就不同,go的定时器并没有使用SIGALARM信号实现,而是采取最小堆的方式实现(源码包中使用数组实现的四叉树),使用这种方式定时精度很高,但是有的时候可能我们不需要这么高精度的实现,为了更高效的利用资源,有的时候也会实现一个精度比较低的算法.
跟golang定时器相关的入口主要有以下几种方法:
1
2
3
4
5
6
|
<-time.Tick(time.Second)
<-time.After(time.Second)
<-time.NewTicker(time.Second).C
<-time.NewTimer(time.Second).C
time.AfterFunc(time.Second, func() { /*do*/ })
time.Sleep(time.Second)
|
这里我们以其中NewTicker为入口,NewTicker的源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
func NewTicker(d Duration) *Ticker {
if d <= 0 {
panic(errors.New("non-positive interval for NewTicker"))
}
c := make(chan Time, 1)
t := &Ticker{
C: c,
r: runtimeTimer{
// when(d)返回一个runtimeNano() + int64(d)的未来时(到期时间)
//runtimeNano运行时当前纳秒时间
when: when(d),
period: int64(d), // 被唤醒的时间
f: sendTime, // 时间到期后的回调函数
arg: c, // 时间到期后的断言参数
},
}
// 将新的定时任务添加到时间堆中
// 编译器会将这个函数翻译为runtime.startTimer(t *runtime.timer)
// time.runtimeTimer翻译为runtime.timer
startTimer(&t.r)
return t
|
这里有个比较重要的是startTimer(&t.r)它的实现被翻译在runtime包内 。
1
2
3
4
5
6
7
8
9
10
11
12
|
func startTimer(t *timer) {
if raceenabled {
racerelease(unsafe.Pointer(t))
}
addtimer(t)
}
func addtimer(t *timer) {
lock(&timers.lock)
addtimerLocked(t)
unlock(&timers.lock)
}
|
上面的代码为了看着方便,我将他们都放在一起 。
下面代码都写出部分注释 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
// 使用锁将计时器添加到堆中
// 如果是第一次运行此方法则启动timerproc
func addtimerLocked(t *timer) {
if t.when < 0 {
t.when = 1<<63 - 1
}
// t.i i是定时任务数组中的索引
// 将新的定时任务追加到定时任务数组队尾
t.i = len(timers.t)
timers.t = append(timers.t, t)
// 使用数组实现的四叉树最小堆根据when(到期时间)进行排序
siftupTimer(t.i)
// 如果t.i 索引为0
if t.i == 0 {
if timers.sleeping {
// 如果还在sleep就唤醒
timers.sleeping = false
// 这里基于OS的同步,并进行OS系统调用
// 在timerproc()使goroutine从睡眠状态恢复
notewakeup(&timers.waitnote)
}
if timers.rescheduling {
timers.rescheduling = false
// 如果没有定时器,timerproc()与goparkunlock共同sleep
// goready这里特殊说明下,在线程创建的堆栈,它比goroutine堆栈大。
// 函数不能增长堆栈,同时不能被调度器抢占
goready(timers.gp, 0)
}
}
if !timers.created {
timers.created = true
go timerproc() //这里只有初始化一次
}
}
// Timerproc运行时间驱动的事件。
// 它sleep到计时器堆中的下一个。
// 如果addtimer插入一个新的事件,它会提前唤醒timerproc。
func timerproc() {
timers.gp = getg()
for {
lock(&timers.lock)
timers.sleeping = false
now := nanotime()
delta := int64(-1)
for {
if len(timers.t) == 0 {
delta = -1
break
}
t := timers.t[0]
delta = t.when - now
if delta > 0 {
break // 时间未到
}
if t.period > 0 {
// 计算下一次时间
// period被唤醒的间隔
t.when += t.period * (1 + -delta/t.period)
siftdownTimer(0)
} else {
// remove from heap
last := len(timers.t) - 1
if last > 0 {
timers.t[0] = timers.t[last]
timers.t[0].i = 0
}
timers.t[last] = nil
timers.t = timers.t[:last]
if last > 0 {
siftdownTimer(0)
}
t.i = -1 // 标记移除
}
f := t.f
arg := t.arg
seq := t.seq
unlock(&timers.lock)
if raceenabled {
raceacquire(unsafe.Pointer(t))
}
f(arg, seq)
lock(&timers.lock)
}
if delta < 0 || faketime > 0 {
// 没有定时器,把goroutine sleep。
timers.rescheduling = true
// 将当前的goroutine放入等待状态并解锁锁。
// goroutine也可以通过呼叫goready(gp)来重新运行。
goparkunlock(&timers.lock, "timer goroutine (idle)", traceEvGoBlock, 1)
continue
}
// At least one timer pending. Sleep until then.
timers.sleeping = true
timers.sleepUntil = now + delta
// 重置
noteclear(&timers.waitnote)
unlock(&timers.lock)
// 使goroutine进入睡眠状态,直到notewakeup被调用,
// 通过notewakeup 唤醒
notetsleepg(&timers.waitnote, delta)
}
}
|
golang使用最小堆(最小堆是满足除了根节点以外的每个节点都不小于其父节点的堆)实现的定时器。golang []*timer结构如下
golang存储定时任务结构 。
addtimer在堆中插入一个值,然后保持最小堆的特性,其实这个结构本质就是最小优先队列的一个应用,然后将时间转换一个绝对时间处理,通过睡眠和唤醒找出定时任务,这里阅读起来源码很容易,所以只将代码和部分注释写出.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我的支持.
原文链接:https://zhuanlan.zhihu.com/p/31634188 。
最后此篇关于golang time包下定时器的实现方法的文章就讲到这里了,如果你想了解更多关于golang time包下定时器的实现方法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
哪种定时器在性能方面更适合使用? Jquery 计时器或 Javascript 计时器。 具有计时器的页面没有任何 Jquery 代码。 谢谢 最佳答案 在仅使用计时器的页面上引用完整的 JQuery
R 语言有没有简单的方法来设置定时器功能?计时器函数是指位于 session 后台并每隔一段时间执行一次的函数。 干杯! 最佳答案 tcltk2 包中有 tclTaskSchedule 函数(和其
我想在点击发生后调用 setTimeout()。 如果用户在 300ms 过去之前再次点击,我想停止那个计时器,触发另一个函数并重新启动原来的计时器。 我知道 setTimeout() 但我不确定如何
请参阅下面的代码...它会在页面加载 + 8 秒后更改图像,然后继续每 1 秒更改一次。 setInterval(function(){ setTimeout(function(){
我正在尝试使用计时器来安排应用程序中的重复事件。但是,我希望能够实时调整事件触发的时间段(根据用户输入)。 例如: public class HelperTimer extends TimerTask
setTimeout()--用于指定在一段特定的时间后执行某段程序。 格式: [定时
setTimeout 和 clearTimeout 复制代码 代码如下: var obj = setTimeout(cb, ms); setTim
if(e.getSource()==continuous) { TimerTask task = new TimerTask() { public void run()
请谁能告诉我如何在 iPhone 的 cocos2d 中实现启动游戏的倒计时器。 我的意思是,按下“播放”时,一个新场景会出现,显示数字“3”、“2”、“1”,然后显示“GO!”一词。 最佳答案 来自
我正在制作一个计时器,而且效果很好。唯一的问题是,每过一秒,它就会在新行中打印剩余的时间(以秒为单位)。我该如何做到这一点,而不是打印一个新行,而只是改变当前行中显示的内容? 这就是我所拥有的...
这个问题在这里已经有了答案: Lua Program Delay (2 个答案) 关闭 7 年前。 我目前使用 Corona SDK,Lua 作为我的主要语言。我在使用此代码时遇到问题 - 当我运行
我正在制作一个计时器,而且效果很好。唯一的问题是,每过一秒,它就会在新行中打印剩余的时间(以秒为单位)。我该如何做到这一点,而不是打印一个新行,而只是改变当前行中显示的内容? 这就是我所拥有的...
到目前为止,我使用的每种方法都只是暂时卡住我的程序,但我希望游戏继续运行,我只希望盾牌 boolean 值在 X 时间内为 true,然后在时间到期后返回 false,有吗有办法做到这一点吗?谢谢。
我需要创建一个异步线程,它运行一次,延迟 2 分钟,并且可以随时终止。我看到了几种可能的解决方案: ScheduledExecutorService 和 FutureTask 允许我中断正在运行的任务
我开发了一个简单的应用程序并使用了计时器,但如果我多次运行计时器,计时器会丢弃此异常:线程“AWT-EventQueue-0”java.lang.IllegalStateException 中的异常:
我正在实现一个计时器: timer = new Timer(); timer.schedule(new TimerTask() { @Overr
我有一个有点复杂的 iOS 用户界面,我需要每秒重新加载 UICollectionView 的特定单元格以显示时间(有点像复杂的秒表),我还需要每秒做一些其他事情在这次通话中。 问题的第 1 部分 我
我一直在研究可用于 QueryPerformanceCounter()/QueryPerformanceFrequency() 的不同类型的计时器,在进一步研究之后,我发现了一个使用计时器类的例子..
我正在尝试以微秒为单位做一个计时器,但它不太管用。 #include #include #include using namespace std; int main () { struc
假设我有一个整数数组 int timeouts [] = {1000 , 2000 , 3000 , 3500}; 我想创建一个计时器,最多计时 3.5 秒,并在毫秒计数等于数组元素之一时调用相同的函
我是一名优秀的程序员,十分优秀!