zoukankan      html  css  js  c++  java
  • 定时器中的内存泄漏

    周期定时器

    func main() {
        timer := time.NewTicker(1 * time.Second)  //NewTicker是周期定时器,NewTimer是普通定时器只能用一次
        for {
            <-timer.C
            fmt.Println("good")
        }
    }

    定时器

        time.Sleep(time.Second)
        //2Timer.C
        myTimer := time.NewTimer(time.Second * 2) //创建定时器,指定定时时长
        nowTime := <-myTimer.C                    //定时满,系统自动写入时间
        fmt.Println("现在时间", nowTime)
        //3 time.After
        nowTime = <-time.After(time.Second * 2)
        fmt.Println("现下时间", nowTime)
    
        //定时器的停止和重置
        myTimer2 := time.NewTimer(time.Second * 3)
        go func() {
            <-myTimer2.C
            fmt.Println("子go程,定时完毕")
        }()
        myTimer2.Stop() //停止
        myTimer.Reset(1 * time.Second) //重置

    下面的写法会造成内存泄漏

    package main
    
    import (
        "time"
    )
    
    func main() {
        ch := make(chan int, 10)
    
        go func() {
            var i= 1
            for {
                i++
                ch <- i
            }
        }()
    
        for {
            select {
            case x := <-ch:
                println(x)
            case <-time.After(3 * time.Minute):
                println(time.Now().Unix())
            }
        }
    }
    `在for循环每次select的时候,都会实例化一个一个新的定时器。该定时器在3分钟后,才会被激活,但是激活后已经跟select无引用关系,被gc给清理掉。
    换句话说,被遗弃的time.After定时任务还是在时间堆里面,定时任务未到期之前,是不会被gc清理的。
    也就是说每次循环实例化的新定时器对象需要3分钟才会可能被GC清理掉,如果我们把上面复现代码中的3分钟改小点,改成10秒钟,通过top命令会发现大概10秒钟后,该程序占用的内存增长到1.05G后基本上就不增长了`
    下面的代码是解决方案
    package main
    
    import (
        "time"
        )
    
    func main()  {
        ch := make(chan int, 10)
    
        go func() {
            for {
                ch <- 100
            }
        }()
    
        idleDuration := 3 * time.Minute
        idleDelay := time.NewTimer(idleDuration) //综上,在go代码中,在for循环里不要使用select + time.After的组合,可以使用time.NewTimer替代
        defer idleDelay.Stop() //记得要关闭定时器
    
        for {
            idleDelay.Reset(idleDuration)
    
            select {
                case x := <- ch:
                    println(x)
                case <-idleDelay.C:
                    return
                }
        }
    }




  • 相关阅读:
    关于在windows平台下将应用制作成windows服务及服务依赖的感想
    mysql 变量赋值的三种方法
    如何上传本地jar至远程仓库供其他项目使用
    maven的标准
    修改idea的缓存
    前端的网站
    读取简单的xml
    IDEA 自动设置compile target变成1.5
    注解导出优化版(推荐,十分强大)
    Linux命令干货!!!最常用的命令
  • 原文地址:https://www.cnblogs.com/hualou/p/12069705.html
Copyright © 2011-2022 走看看