Как работает тикер Golang?

func Tick() {                                                                                                                                         
    fmt.Println("startTime", time.Now().Format("2006-01-02 15:04:05"))                                                                                
    t := time.NewTicker(time.Second * 3)                                                                                                              
    time.Sleep(time.Second * 12)                                                                                                                      
    for {                                                                                                                                             
        stamp := <-t.C                                                                                                                                
        fmt.Println("tickTime", stamp.Format("2006-01-02 15:04:05"))                                                                                  
    }                                                                                                                                                 
}          

Вывод из приведенного выше фрагмента:

время начала 2016-06-22 16:22:20

tickTime 22.06.2016 16:22:23

tickTime 22.06.2016 16:22:35

tickTime 22.06.2016 16:22:38

tickTime 22.06.2016 16:22:41

tickTime 22.06.2016 16:22:44


Почему это произошло без метки времени 16:22:26, ​​16:22:29, когда я задерживаю тикер?


person what is what    schedule 22.06.2016    source источник
comment
Где ты это делаешь? У меня вроде работает нормально: play.golang.org/p/3uVTJq9AfN   -  person Duru Can Celasun    schedule 22.06.2016
comment
@DuruCanCelasun Вы ждете всего 1 секунду, что меньше продолжительности тикера. Подождите › длительность тика здесь проблема.   -  person LinearZoetrope    schedule 22.06.2016


Ответы (1)


Это источник тикера (извините за номера строк, я скопировал это со страницы источника документации):

    func NewTicker(d Duration) *Ticker {
            if d <= 0 {
                panic(errors.New("non-positive interval for NewTicker"))
            }
            // Give the channel a 1-element time buffer.
            // If the client falls behind while reading, we drop ticks
            // on the floor until the client catches up.
            c := make(chan Time, 1)
            t := &Ticker{
                C: c,
                r: runtimeTimer{
                    when:   when(d),
                    period: int64(d),
                    f:      sendTime,
                    arg:    c,
                },
            }
            startTimer(&t.r)
            return t
        }

Обратите внимание на комментарий

// Give the channel a 1-element time buffer.
// If the client falls behind while reading, we drop ticks
// on the floor until the client catches up.

Что творится:

  1. Вы создаете таймер
  2. Таймер производит свой первый тик и буферизует его.
  3. Теперь он ждет, просыпается и блокируется, ожидая, пока вы потребите, чтобы он мог произвести такт 2.
  4. В конце концов, ваша горутина просыпается и немедленно потребляет первые два тика, которые она произвела, и снова начинает производить тики.

Редактировать: Кроме того, документация для NewTicker (для которой Tick является удобной функцией) гласит:

NewTicker возвращает новый тикер, содержащий канал, который будет отправлять время с периодом, заданным аргументом продолжительности. Он регулирует интервалы или отбрасывает тики, чтобы компенсировать медленные приемники. Длительность d должна быть больше нуля; если нет, NewTicker запаникует. Остановите бегущую строку, чтобы освободить связанные ресурсы.

Хотя явно не упоминается, что это канал с буфером, равным единице.

person LinearZoetrope    schedule 22.06.2016