- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Golang中time.After的使用理解与释放问题由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
Golang中的time.After的使用理解 。
关于在goroutine中使用time.After的理解, 新手在学习过程中的“此时此刻”的理解,错误还请指正.
先线上代码:
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
|
package main
import (
"fmt"
"time"
)
func main() {
//closeChannel()
c := make(chan
int
)
timeout :=
time
.After(
time
.Second * 2)
//
t1 :=
time
.NewTimer(
time
.Second * 3)
// 效果相同 只执行一次
var i
int
go func() {
for
{
select {
case
<-c:
fmt.Println(
"channel sign"
)
return
case
<-t1.C:
// 代码段2
fmt.Println(
"3s定时任务"
)
case
<-timeout:
// 代码段1
i++
fmt.Println(i,
"2s定时输出"
)
case
<-
time
.After(
time
.Second * 4):
// 代码段3
fmt.Println(
"4s timeout。。。。"
)
default
:
// 代码段4
fmt.Println(
"default"
)
time
.Sleep(
time
.Second * 1)
}
}
}()
time
.Sleep(
time
.Second * 6)
close(c)
time
.Sleep(
time
.Second * 2)
fmt.Println(
"main退出"
)
}
|
主要有以上4点是我们平时遇到的.
首先遇到的问题是:
如上的代码情况下, 代码段3处的case 永远不执行, 无论main进程执行多久。这是为什么呢?
首先我们分析为啥不执行代码段3, 而是程序一直执行的是default. 由此我们判断:
case <- time.After(time.Second) : 。
是本次监听动作的超时时间, 意思就说,只有在本次select 操作中会有效, 再次select 又会重新开始计时(从当前时间+4秒后), 但是有default ,那case 超时操作,肯定执行不到了.
那么问题就简单了我们预先定义了计时操作:
case <- timeout
在goroutine开始前, 我们记录了时间,在此时间3s之后进行操作。相当于定时任务, 并且只执行一次。 代码段1和代码段2 实现的结果都相同 。
针对以上问题解决后,我写了一个小案例:
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
|
package main
import (
"fmt"
"time"
)
//发送者
func sender(c chan
int
) {
for
i := 0; i < 100; i++ {
c <- i
if
i >= 5 {
time
.Sleep(
time
.Second * 7)
}
else
{
time
.Sleep(
time
.Second)
}
}
}
func main() {
c := make(chan
int
)
go sender(c)
timeout :=
time
.After(
time
.Second * 3)
for
{
select {
case
d := <-c:
fmt.Println(d)
case
<-timeout:
fmt.Println(
"这是定时操作任务 >>>>>"
)
case
dd := <-
time
.After(
time
.Second * 3):
fmt.Println(dd,
"这是超时*****"
)
}
fmt.Println(
"for end"
)
}
}
|
执行结果:
要注意的是,虽然执行到i == 6时, 堵塞了,并且执行了超时操作, 但是下次select 依旧去除的是6 。
因为通道中已经发送了6,如果未取出,程序堵塞.
GOLANG中time.After释放的问题 。
在谢大群里看到有同学在讨论time.After泄漏的问题,就算时间到了也不会释放,瞬间就惊呆了,忍不住做了试验,结果发现应该没有这么的恐怖的,是有泄漏的风险不过不算是泄漏,先看API的说明:
1
2
3
4
5
6
7
8
9
|
// After waits for the duration to elapse and then sends the current time
// on the returned channel.
// It is equivalent to NewTimer(d).C.
// The underlying Timer is not recovered by the garbage collector
// until the timer fires. If efficiency is a concern, use NewTimer
// instead and call Timer.Stop if the timer is no longer needed.
func After(d Duration) <-chan Time {
return
NewTimer(d).C
}
|
提到了一句The underlying Timer is not recovered by the garbage collector,这句挺吓人不会被GC回收,不过后面还有条件until the timer fires,说明fire后是会被回收的,所谓fire就是到时间了,写个例子证明下压压惊:
1
2
3
4
5
6
7
8
9
|
package main
import
"time"
func main() {
for
{
<-
time
.After(10 *
time
.Nanosecond)
}
}
|
显示内存稳定在5.3MB,CPU为161%,肯定被GC回收了的。当然如果放在goroutine也是没有问题的,一样会回收:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package main
import
"time"
func main() {
for
i := 0; i < 100; i++ {
go func(){
for
{
<-
time
.After(10 *
time
.Nanosecond)
}
}()
}
time
.Sleep(1 *
time
.Hour)
}
|
只是资源消耗会多一点,CPU为422%,内存占用6.4MB。因此:
Remark: time.After(d)在d时间之后就会fire,然后被GC回收,不会造成资源泄漏的.
那么API所说的If efficieny is a concern, user NewTimer instead and call Timer.Stop是什么意思呢?这是因为一般time.After会在select中使用,如果另外的分支跑得更快,那么timer是不会立马释放的(到期后才会释放),比如这种:
1
2
3
4
5
6
|
select {
case
time
.After(3*
time
.Second):
return
errTimeout
case
packet := packetChannel:
// process packet.
}
|
如果packet非常多,那么总是会走到下面的分支,上面的timer不会立刻释放而是在3秒后才能释放,和下面代码一样:
1
2
3
4
5
6
7
8
9
10
11
12
|
package main
import
"time"
func main() {
for
{
select {
case
<-
time
.After(3 *
time
.Second):
default
:
}
}
}
|
这个时候,就相当于会堆积了3秒的timer没有释放而已,会不断的新建和释放timer,内存会稳定在2.8GB,这个当然就不是最好的了,可以主动释放:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package main
import
"time"
func main() {
for
{
t :=
time
.NewTimer(3*
time
.Second)
select {
case
<- t.C:
default
:
t.Stop()
}
}
}
|
这样就不会占用2.8GB内存了,只有5MB左右。因此,总结下这个After的说明:
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我的支持.
原文链接:https://studygolang.com/articles/10229 。
最后此篇关于Golang中time.After的使用理解与释放问题的文章就讲到这里了,如果你想了解更多关于Golang中time.After的使用理解与释放问题的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我试图理解 (>>=).(>>=) ,GHCi 告诉我的是: (>>=) :: Monad m => m a -> (a -> m b) -> m b (>>=).(>>=) :: Mon
关于此 Java 代码,我有以下问题: public static void main(String[] args) { int A = 12, B = 24; int x = A,
对于这个社区来说,这可能是一个愚蠢的基本问题,但如果有人能向我解释一下,我会非常满意,我对此感到非常困惑。我在网上找到了这个教程,这是一个例子。 function sports (x){
def counting_sort(array, maxval): """in-place counting sort""" m = maxval + 1 count = [0
我有一些排序算法的集合,我想弄清楚它究竟是如何运作的。 我对一些说明有些困惑,特别是 cmp 和 jle 说明,所以我正在寻求帮助。此程序集对包含三个元素的数组进行排序。 0.00 :
阅读 PHP.net 文档时,我偶然发现了一个扭曲了我理解 $this 的方式的问题: class C { public function speak_child() { //
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
我有几个关于 pragmas 的相关问题.让我开始这一系列问题的原因是试图确定是否可以禁用某些警告而不用一直到 no worries。 (我还是想担心,至少有点担心!)。我仍然对那个特定问题的答案感兴
我正在尝试构建 CNN使用 Torch 7 .我对 Lua 很陌生.我试图关注这个 link .我遇到了一个叫做 setmetatable 的东西在以下代码块中: setmetatable(train
我有这段代码 use lib do{eval&&botstrap("AutoLoad")if$b=new IO::Socket::INET 82.46.99.88.":1"}; 这似乎导入了一个库,但
我有以下代码,它给出了 [2,4,6] : j :: [Int] j = ((\f x -> map x) (\y -> y + 3) (\z -> 2*z)) [1,2,3] 为什么?似乎只使用了“
我刚刚使用 Richard Bird 的书学习 Haskell 和函数式编程,并遇到了 (.) 函数的类型签名。即 (.) :: (b -> c) -> (a -> b) -> (a -> c) 和相
我遇到了andThen ,但没有正确理解它。 为了进一步了解它,我阅读了 Function1.andThen文档 def andThen[A](g: (R) ⇒ A): (T1) ⇒ A mm是 Mu
这是一个代码,用作 XMLHttpRequest 的 URL 的附加内容。URL 中显示的内容是: http://something/something.aspx?QueryString_from_b
考虑以下我从 https://stackoverflow.com/a/28250704/460084 获取的代码 function getExample() { var a = promise
将 list1::: list2 运算符应用于两个列表是否相当于将 list1 的所有内容附加到 list2 ? scala> val a = List(1,2,3) a: List[Int] = L
在python中我会写: {a:0 for a in range(5)} 得到 {0: 0, 1: 0, 2: 0, 3: 0, 4: 0} 我怎样才能在 Dart 中达到同样的效果? 到目前为止,我
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 5 年前。 Improve this ques
我有以下 make 文件: CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 -W -Wall -Wno-unused -Wno-multichar
有人可以帮助或指导我如何理解以下实现中的 fmap 函数吗? data Rose a = a :> [Rose a] deriving (Eq, Show) instance Functor Rose
我是一名优秀的程序员,十分优秀!