golang-定时器

2020-02-03  本文已影响0人  爱吃豆包

定时器 和 断续器

定时器:延时某些操作任务
断续器:设置的好间隔时间,周而复始的执行任务

package main

import (
    "fmt"
    "time"
)

// 定时器  和 断续器
/**

    定时器:延时某些操作任务
    断续器:设置的好间隔时间,周而复始的执行任务

    有两种方式创建定时器:
        time.NewTimer 函数 和 time.AfterFunc 函数
        这两个函数将得到 time.Timer 类型

        // timer.Reset(time.Second * 3) 重置定时器,并设置定时器间隔时间
        // timer.Stop() 停止定时器
        // time.Sleep(time.Second) // 睡眠,一秒

        timer.Reset(...) 和 timer.Sleep() 返回值是一个 bool 值。
        如果值为 false 表示,这个定时器已经过期(或者结束了),
        如果值为 true 表示,已经成功 重置 或者 停止


        time.NewTimer 函数 和 time.AfterFunc 函数 创建的定时器只能执行一次,
        需要配合 for 和 select 才能周而复始的执行


    断续器:
        time.NewTicker 函数创建, 可以周而复始的执行,比如每次间隔3秒执行一次任务

**/

// ========================  定时器

// 定时器例子 time.NewTimer 方式
func timer1() {

    // 这里的定时器,执行完就会结束(因为main函数结束了),如果想周而复始的执行,使用 for 和 select 方式

    // 创建一个到期时间的间隔为 3 秒的定时器
    // 参数 time.Duration 类型
    timer := time.NewTimer(time.Second * 3)
    fmt.Printf("定时器开始时间:%v\n", time.Now().Format("2006-01-02 15:04:05"))
    // <-timer.C 表示接收这个管道的值, 传递过来的是它到期的时间

    // 间隔一段时间执行下面的代码, 管道有值表示定时器的执行任务的时间到了
    expTime := <-timer.C
    fmt.Printf("定时器结束时间:%v\n", time.Now().Format("2006-01-02 15:04:05"))
    // 指定自定义的时间进行格式化
    // time.Parse("2006-01-02 15:04:05", "2020-10-01 10:10:01")
    fmt.Printf("接收定时器管道的值:%v", expTime.Format("2006-01-02 15:04:05"))
    fmt.Printf("停止定时器:%v", timer.Stop())

    // timer.Reset(time.Second * 3) 重置定时器,并设置定时器间隔时间
    // timer.Stop() 停止定时器
    // time.Sleep(time.Second) // 睡眠,一秒
}

// 定时器例子 time.AfterFunc 方式
func timer2() {
    // 这里的定时器,执行完就会结束(因为main函数结束了),如果想周而复始的执行,使用 select 方式

    // 创建一个到期时间的间隔为 3 秒的定时器
    time.AfterFunc(time.Second*3, func() {
        // 我需要执行操作...
        fmt.Printf("定时器执行中!")
    })

    // time.AfterFunc 函数不会往 C <- timer.C 管道中发送数据,而是启用 goroutine 去执行传递进去的函数
}

// 定时器例子
// 上面的例子,会发现只执行了一次,
// 这个例子适用于指定我们需要执行的次数
// 这里使用 time.NewTimer 做例子
func timer3() {

    t := time.Second * 3
    var timer *time.Timer

    // 执行任务的通信管道
    intChan := make(chan int, 1)
    go func() {
        // 设置需要执行次数
        // 比如只需执行两次
        for i := 0; i < 2; i++ {
            intChan <- i
            time.Sleep(time.Second)
        }
        // 关闭这个管道
        close(intChan)
    }()

    for {
        if timer == nil {
            timer = time.NewTimer(t)
        } else {
            // 通过 timer.Reset 函数重置这个定时器,达到目的
            // 将超时时间重置
            timer.Reset(t)
        }

        // 堵塞,谁有数据,就执行谁
        // 只会执行一次
        // 如果配合 for 死循环,可以达到一直监听管道的目的
        select {
        case e, ok := <-intChan:
            // 如果管道关闭,表示这个 intChan 管道不可用使用,那么这个 ok 就是 false
            if !ok {
                // 结束这个定时器
                return
            }
            fmt.Printf("定时器正在执行任务!时间:%v\t, 管道值:%v\n", time.Now().Format("2006-01-02 15:04:05"), e)
        case <-timer.C:
            // 如果 intChan 超过 3秒 没有数据,则会执行
            fmt.Printf("超时!\n")
        }
    }

}

// 定时器例子,达到 断续器 的效果,周而复始执行
func timer4() {
    t := time.Second * 3
    var timer *time.Timer

    for {
        if timer == nil {
            timer = time.NewTimer(t)
        } else {
            // 通过 timer.Reset 函数重置这个定时器,达到目的
            // 将超时时间重置
            timer.Reset(t)
        }

        // 堵塞,谁有数据,就执行谁
        // 只会执行一次
        // 如果配合 for 死循环,可以达到一直监听管道的目的
        select {
        case <-timer.C:
            fmt.Printf("执行任务,当前时间:%v\n", time.Now().Format("2006-01-02 15:04:05"))
        }
    }
}

// ======================  断续器

// 周而复始的执行
func timer5() {
    ticker := time.NewTicker(time.Second * 3)
    for {
        select {
        case <-ticker.C:
            fmt.Printf("执行任务,当前时间:%v\n", time.Now().Format("2006-01-02 15:04:05"))
        }
    }
    // ticker.Stop() 停止断续器
}

func main() {
    go timer4()

    // 主线程 睡眠 10 秒
    time.Sleep(time.Second * 10)

}

上一篇下一篇

猜你喜欢

热点阅读