Problem with tickers in go

1

Good morning, I hope you can support me. I'm doing a dummy to test the tickers in go:

package main
import(
    "fmt"
    "time"
)
func main(){
    ticker := time.NewTicker(time.Millisecond * 500) 
    go func() {
        for t := range ticker.C { 
            fmt.Println("Tic a las", t)
        }
    }()
    time.Sleep(time.Millisecond * 1500) 
    ticker.Stop()
    fmt.Println("Ticker detenido:", time.Now())

    var input string
    fmt.Scanln(&input)
    fmt.Println("done")
}

In theory, the ticker runs every 500 milliseconds and I stop it after 1500 milliseconds, so 3 ticker impressions should appear (in theory). However I got the following output:

Tic a las 2016-04-13 09:56:11.8632579 -0500 CDT
Tic a las 2016-04-13 09:56:12.363399 -0500 CDT
Ticker detenido: 2016-04-13 09:56:12.8634635 -0500 CDT

So, add the last 3 lines of the code to finish the program when you press a key, and trying again I found this:

Tic a las 2016-04-13 10:08:15.4709006 -0500 CDT
Tic a las 2016-04-13 10:08:15.9713121 -0500 CDT
Ticker detenido: 2016-04-13 10:08:16.4714132 -0500 CDT
Tic a las 2016-04-13 10:08:16.4714132 -0500 CDT

As you can see, the last two lines print 2016-04-13 10:08:16. 4714132 , it's the same date, even in milliseconds, but the main and I print first I need the print of the ticker printed first. Is there any way to correct this? Any way to give priority to the ticker thread over the main one? I hope you can support me Thanks and regards

    
asked by abrahamhs 13.04.2016 в 17:18
source

1 answer

1

Returning to your first attempt I see that everything is "right".

package main

import(
    "fmt"
    "time"
)

func main(){
    ticker := time.NewTicker(time.Millisecond * 500) 
    go func() {
        for t := range ticker.C { 
            fmt.Println("Tic a las", t)
        }
    }()
    time.Sleep(time.Millisecond * 1500) 
    ticker.Stop()
    fmt.Println("Ticker detenido:", time.Now())
}

When executing it multiple times you will notice that sometimes it prints two lines, as you have put in your question, and other times it prints three lines (in both cases without counting the line of Tic detenido ).

What happens is that the last Tic happens at the same time as the ticker.Stop and sometimes it will not give time to print the last execution of fmt.Println("Tic a las", t) depending on the load of your processor at that moment.

To avoid this inconsistent behavior, it is enough to add a few milli seconds to Sleep to give enough time to print three times the Tic that is inside the cycle.

Something like this:

package main

import "time"
import "fmt"

func main() {
    ticker := time.NewTicker(time.Millisecond * 500)
    go func() {
        for t := range ticker.C {
            fmt.Println("Tick at", t)
        }
    }()
    time.Sleep(time.Millisecond * 1505)
    ticker.Stop()
    fmt.Println("Ticker detenido")
}

I could give you the false impression that it should not happen like this because go is synchronous but what happens is that when you execute go func() you are creating an asynchronous subroutine that runs at the same rate as time.Sleep and therefore is that the entire program does not stop working while the main thread is "asleep".

    
answered by 13.04.2016 / 22:48
source