等待管道结束之前周期的做一些事情,wait是个很好的选择。直接看代码怎么实现

func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding bool, stopCh <-chan struct{}) {
    for {

        select {
        case <-stopCh:
            return
        default:
        }

        jitteredPeriod := period
        if jitterFactor > 0.0 {
            jitteredPeriod = Jitter(period, jitterFactor)
        }

        var t *time.Timer
        if !sliding {
            t = time.NewTimer(jitteredPeriod)
        }

        func() {
            defer runtime.HandleCrash()
            f()
        }()

        if sliding {
            t = time.NewTimer(jitteredPeriod)
        }

        select {
        case <-stopCh:
            return
        case <-t.C:
        }
    }
}

上面的sliding是个很有意思的设计,它确定系统周期调用的时候,计时的起点,如果是TRUE的话,就是f函数执行完成后计时周期,看看利用上面函数实现的两个函数

func Until(f func(), period time.Duration, stopCh <-chan struct{}) {
    JitterUntil(f, period, 0.0, true, stopCh)
}

func NonSlidingUntil(f func(), period time.Duration, stopCh <-chan struct{}) {
    JitterUntil(f, period, 0.0, false, stopCh)
}

分别传入ture和false。
下面看看使用

    ch := make(chan struct{})
    go func() {

        fmt.Println("sleep 1")
        time.Sleep(1*time.Second)
        close(ch)

    }()
    wait.Until(func() {
        time.Sleep(100*time.Millisecond)
        fmt.Println("should not have been invoked")
    }, 100000000, ch)

    fmt.Println("end")

先睡眠一秒,在这一秒钟内,执行周期是0.1秒,然后函数执行耗时0.1秒,这样在一秒内只能执行5次。
输出结果如下:
sleep 1
should not have been invoked
should not have been invoked
should not have been invoked
should not have been invoked
should not have been invoked
end
如果使用NonSlidingUntil
输出结果如下:
sleep 1
should not have been invoked
should not have been invoked
should not have been invoked
should not have been invoked
should not have been invoked
should not have been invoked
should not have been invoked
should not have been invoked
should not have been invoked
should not have been invoked
end
执行了10次,排除了函数自己执行的时间。

更多推荐

kubernetes源码阅读之工具函数wait使用