This is the 24th day of my participation in the August More Text Challenge

This article appears in my column:Let’s Golang

Talk about the fixed time timer and periodic time timer of Go

When we wanted to do delayed execution in scheduling, we could use pipe blocking until someone wrote something into the pipe, and we could use sleep to sleep, but sleeping, the coroutine didn’t do anything and took up resources. So we’re going to use the timer that we’re going to talk about, and we’re not going to use up resources like sleep.

Let’s start with the following code:

package main
​
import (
    "fmt"
    "time"
)
​
func main(a) {
    timer := time.NewTimer(3 * time.Second)
    fmt.Println("Timer created!")
    fmt.Println(time.Now())
    // Block for 3 seconds to read the time
    x := <- timer.C
    // C is a one-way read-only pipe
    fmt.Println(x)
}
Copy the code

The result looks like this:

Timer created!2021- 08- 24 14:02:28.6664158 +0800 CST m=+0.012997601
2021- 08- 24 14:02:31.670071 +0800 CST m=+3.016652801
Copy the code

As you can see, the result is basically the same as what we want to achieve. After creating the three-second timer, block for three seconds before reading the time.

Let’s take a look at this

x := <- timer.C
Copy the code

C is a one-way read-only pipe:

type Timer struct {
    C <-chan Time
    r runtimeTimer
}
Copy the code

If you wanted to describe a one-way write-only pipe, you would write:

C chan <- Time
Copy the code

But if we want to achieve the same goal, we can use the following simpler way:

func main(a) {
    fmt.Println(time.Now())
    x := <- time.After(3*time.Second)
    fmt.Println(x)
}
Copy the code

Use time.after () to wait a specified amount of time, and then send the current time on the returned pipe. It is equivalent to NewTimer(d).c. The garbage collector does not collect the underlying Timer until the Timer is triggered. If efficiency is a concern, use NewTimer instead and end with a call to timer.stop when the Timer is no longer needed.

Of course we can also use the following method, both methods can be used:

x := <- time.NewTimer(3 * time.Second).C
Copy the code

The fixed time timer is a time bomb set to three seconds that will explode in three seconds. Now let’s look at the periodic time timer!

func main(a) {
    ticker := time.NewTicker(1 * time.Second)
​
    var i int
    for{
        x := <- ticker.C
        fmt.Print("\r",x)
        i++
        if i>3{
            // Stopping the stopwatch causes ticker.C to never read data,
            // This will cause a deadlock.
            ticker.Stop()
            break
        }
    }
    fmt.Println("The clock is over.")}Copy the code

Set a periodic timer, read data from the pipe every second, and output until I >3. Use ticker.stop () to terminate the timer, then Stop the loop, and tell you that the timer is finished.

If you still want to read after the timer is over, the following situation will occur!

fatal error: all goroutines are asleep – deadlock!

Deadlock! So we need break here.