Skip to content

Latest commit

ย 

History

History
783 lines (678 loc) ยท 41.5 KB

timer.md

File metadata and controls

783 lines (678 loc) ยท 41.5 KB

ๅฎšๆ—ถๅ™จ

็ฎ€ๅ•็”จๆณ•

ไป€ไนˆ Date๏ผŒParse๏ผŒParseInLocation๏ผŒๅฐฑไธ่ฏดไบ†ใ€‚ไธป่ฆๅ…ณๆณจไธ‹้ขๅ‡ ไธชๅ‡ฝๆ•ฐ๏ผš

ticker ็›ธๅ…ณ

func Tick(d Duration) <-chan Time
func NewTicker(d Duration) *Ticker
func (t *Ticker) Stop()
package main

import (
    "fmt"
    "time"
)

func main() {
    for t := range time.Tick(time.Second * 2) {
        fmt.Println(t, "hello world")
    }
}
package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(time.Second * 2)
    for {
        select {
        case t := <-ticker.C:
            fmt.Println(t, "hello world")
        }
    }
}

้œ€่ฆๆณจๆ„็š„ๆ˜ฏ๏ผŒticker ๅœจไธไฝฟ็”จๆ—ถ๏ผŒๅบ”่ฏฅๆ‰‹ๅŠจ stop๏ผŒๅฆ‚ๆžœไธ stop ๅฏ่ƒฝไผš้€ ๆˆ timer ๆณ„้œฒ๏ผŒๆฏ”ๅฆ‚ไธ‹้ข่ฟ™ๆ ท็š„ไปฃ็ :

package main

import (
    "fmt"
    "time"
)

func main() {
    for {
        select {
        case t := <-time.Tick(time.Second * 2):
            fmt.Println(t, "hello world")
        }
    }
}

ๆณ„้œฒไน‹ๅŽไผšๅœจๆ—ถ้—ดๅ †ไธญ็ดฏ็งฏ่ถŠๆฅ่ถŠๅคš็š„ timer ๅฏน่ฑก๏ผŒไปŽ่€Œๅ‘็”Ÿๆ›ด้บป็ƒฆ็š„้—ฎ้ข˜ใ€‚

timer ็›ธๅ…ณ

func After(d Duration) <-chan Time
func NewTimer(d Duration) *Timer
func (t *Timer) Reset(d Duration) bool
func (t *Timer) Stop() bool

time.After ไธ€่ˆฌ็”จๆฅๆŽงๅˆถๆŸไบ›่€—ๆ—ถ่พƒ้•ฟ็š„่กŒไธบ๏ผŒๅœจ่ถ…ๆ—ถๅŽไธๅ†็ญ‰ๅพ…๏ผŒไปฅไฝฟ็จ‹ๅบ่กŒไธบๅฏ้ข„ๆœŸใ€‚ๅฆ‚ๆžœไธๅš่ถ…ๆ—ถๅ–ๆถˆ้‡Šๆ”พ่ต„ๆบ๏ผŒๅˆ™ๅฏ่ƒฝๅ› ไธบไพ่ต–ๆ–นๅ“ๅบ”็ผ“ๆ…ข่€Œๅฏผ่‡ดๆœฌๅœฐ่ต„ๆบๅ †็งฏ๏ผŒไพ‹ๅฆ‚ fd๏ผŒ่ฟžๆŽฅๆ•ฐ๏ผŒๅ†…ๅญ˜ๅ ็”จ็ญ‰็ญ‰ใ€‚ไปŽ่€Œๅฏผ่‡ดๆœๅŠกๅฎ•ๆœบใ€‚

่ฟ™้‡Œ็”จ้˜ปๅกž channel ่ฏปๅ–ไผšๆฐธ่ฟœ้˜ปๅกž็š„็‰นๆ€งๆฅๆจกๆ‹Ÿ่พƒ้•ฟๆ—ถ้—ด็š„่กŒไธบ๏ผŒๅœจ่ถ…ๆ—ถๅŽไผšไปŽ select ไธญ่ทณๅ‡บใ€‚

package main

import "time"

func main() {
    var ch chan int
    select {
    case <-time.After(time.Second):
        println("time out, and end")
    case <-ch:
    }
}

time.After ๅ’Œ time.Tick ไธๅŒ๏ผŒๆ˜ฏไธ€ๆฌกๆ€ง่งฆๅ‘็š„๏ผŒ่งฆๅ‘ๅŽ timer ๆœฌ่บซไผšไปŽๆ—ถ้—ดๅ †ไธญๅˆ ้™คใ€‚ๆ‰€ไปฅไธ€่ˆฌๆƒ…ๅ†ตไธ‹็›ดๆŽฅ็”จ <-time.After ๆ˜ฏๆฒกๆœ‰้—ฎ้ข˜็š„๏ผŒไธ่ฟ‡ๅœจ for ๅพช็Žฏ็š„ๆ—ถๅ€™่ฆๆณจๆ„:

package main

import "time"

func main() {
    var ch = make(chan int)
    go func() {
        for {
            ch <- 1
        }
    }()

    for {
        select {
        case <-time.After(time.Second):
            println("time out, and end")
        case <-ch:
        }
    }
}

ไธŠ้ข็š„ไปฃ็ ๏ผŒ<-ch ่ฟ™ไธช case ๆฏๆฌกๆ‰ง่กŒ็š„ๆ—ถ้—ด้ƒฝๅพˆ็Ÿญ๏ผŒไฝ†ๆฏๆฌก่ฟ›ๅ…ฅ select๏ผŒtime.After ้ƒฝไผšๅˆ†้…ไธ€ไธชๆ–ฐ็š„ timerใ€‚ๅ› ๆญคไผšๅœจ็Ÿญๆ—ถ้—ดๅ†…ๅˆ›ๅปบๅคง้‡็š„ๆ— ็”จ timer๏ผŒ่™ฝ็„ถๆฒก็”จ็š„ timer ๅœจ่งฆๅ‘ๅŽไผšๆถˆๅคฑ๏ผŒไฝ†่ฟ™็งๅ†™ๆณ•ไผš้€ ๆˆๆ— ๆ„ไน‰็š„ cpu ่ต„ๆบๆตช่ดนใ€‚ๆญฃ็กฎ็š„ๅ†™ๆณ•ๅบ”่ฏฅๅฏน timer ่ฟ›่กŒ้‡็”จ๏ผŒๅฆ‚ไธ‹:

package main

import "time"

func main() {
    var ch = make(chan int)
    go func() {
        for {
            ch <- 1
        }
    }()

    timer := time.NewTimer(time.Second)
    for {
        timer.Reset(time.Second)
        select {
        case <-timer.C:
            println("time out, and end")
        case <-ch:
        }
    }
}

ๅ’Œ Ticker ไธ€ๆ ท๏ผŒๅฆ‚ๆžœไน‹ๅ‰็š„ timer ๆฒก็”จไบ†๏ผŒๅฏไปฅๆ‰‹ๅŠจ Stop ไปฅไฝฟ่ฏฅ timer ไปŽๆ—ถ้—ดๅ †ไธญ็งป้™คใ€‚

ๆบ็ ๅˆ†ๆž

ๆ•ฐๆฎ็ป“ๆž„

                                          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                                                                     
                                          โ”‚ timers โ”‚                                                                                                     
                                          โ”œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”                                              
                                          โ”‚    โ”‚    โ”‚    โ”‚    โ”‚    โ”‚    โ”‚    โ”‚                       โ”‚    โ”‚                                              
                                          โ”‚  0 โ”‚  1 โ”‚  2 โ”‚  3 โ”‚  4 โ”‚  5 โ”‚  6 โ”‚            ...        โ”‚ 63 โ”‚                                              
                                          โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”˜                                              
                                              โ”‚                                                         โ”‚                                                
                                              โ”‚                                                         โ”‚                                                
                                              โ”‚                                                         โ”‚                                                
                                              โ”‚                                                         โ”‚                                                
                                              โ”‚                                                         โ”‚                                                
                                              โ”‚ โ”‚                                          โ”‚            โ”‚    โ”‚                                          โ”‚
                                              โ”‚ โ”‚          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”          โ”‚            โ”‚    โ”‚          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”          โ”‚
                                              โ”‚ โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ โ”‚   cacheline size   โ”‚ โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค            โ”‚    โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ โ”‚   cacheline size   โ”‚ โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
                                              โ”‚ โ”‚          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜          โ”‚            โ”‚    โ”‚          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜          โ”‚
                                              โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค            โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
                                              โ””โ–ถโ”‚timersBucket โ”‚                 โ”‚          โ”‚            โ””โ”€โ”€โ”€โ–ถโ”‚timersBucket โ”‚                 โ”‚          โ”‚
                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   pad    โ”‚                 โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   pad    โ”‚
                                                โ”‚          lock mutex           โ”‚          โ”‚                 โ”‚          lock mutex           โ”‚          โ”‚
                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚                 โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚
                                                โ”‚             gp *g             โ”‚          โ”‚                 โ”‚             gp *g             โ”‚          โ”‚
                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚                 โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚
                                                โ”‚         created bool          โ”‚          โ”‚                 โ”‚         created bool          โ”‚          โ”‚
                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚    ........     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚
                                                โ”‚         sleeping bool         โ”‚          โ”‚                 โ”‚         sleeping bool         โ”‚          โ”‚
                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚                 โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚
                                                โ”‚       rescheduling bool       โ”‚          โ”‚                 โ”‚       rescheduling bool       โ”‚          โ”‚
                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚                 โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚
                                                โ”‚       sleepUntil int64        โ”‚          โ”‚                 โ”‚       sleepUntil int64        โ”‚          โ”‚
                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚                 โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚
                                                โ”‚         waitnote note         โ”‚          โ”‚                 โ”‚         waitnote note         โ”‚          โ”‚
                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚                 โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค          โ”‚
                                                โ”‚          t []*timer           โ”‚          โ”‚                 โ”‚          t []*timer           โ”‚          โ”‚
                                                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                 โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                                โ”‚                                                                                        
                                                                โ”‚                                                                                        
                                                                โ”‚                                                                                        
                                                                โ–ผ                                                                                        
                                                              โ”Œโ”€โ”€โ”€โ”                                                                                      
                                                              โ”‚ 0 โ”‚                                                                                      
                                                              โ””โ”€โ”€โ”€โ”˜                                                                                      
                                                                โ”‚                                                                                        
                                                                โ”‚                                                                                        
                                                                โ”‚                                                                                        
                                                                โ”‚                                                                                        
                                                                โ–ผ                                                                                        
                                                        โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”                                                                                
                                                        โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚                                                                                
                                                        โ””โ”€โ”ฌโ”€โ”ดโ”€โ”ฌโ”€โ”ดโ”€โ”ฌโ”€โ”ดโ”€โ”ฌโ”€โ”˜                                                                                
                        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚   โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                       
                        โ”‚                              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                     โ”‚                                       
                        โ–ผ                              โ”‚                   โ”‚                                     โ–ผ                                       
                โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”                      โ–ผ                   โ–ผ                             โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”                               
                โ”‚   โ”‚   โ”‚   โ”‚   โ”‚              โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”                     โ”‚   โ”‚   โ”‚   โ”‚   โ”‚                               
                โ””โ”€โ”ฌโ”€โ”ดโ”€โ”ฌโ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜              โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚                     โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”ฌโ”€โ”ดโ”€โ”ฌโ”€โ”˜                               
                  โ”‚   โ”‚                        โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜                               โ”‚   โ”‚                                 
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                                        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”                           
        โ”‚                       โ”‚                                                                        โ”‚                   โ”‚                           
        โ”‚                       โ”‚                                                                        โ”‚                   โ”‚                           
        โ–ผ                       โ–ผ                                                                        โ–ผ                   โ–ผ                           
โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”                                                        โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”                   
โ”‚   โ”‚   โ”‚   โ”‚   โ”‚       โ”‚   โ”‚   โ”‚   โ”‚   โ”‚                  .................                     โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚                   
โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜       โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜                                                        โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜                   

ไธ‹้ข็š„็ป“่ฎบ้ƒฝๅฏไปฅ็ป“ๅˆไธŠ้ข็š„ๅ›พๆฅ็œ‹ใ€‚

ๅœจ runtime/time.go ไธญๅฎšไน‰ไบ† timers ๆ•ฐ็ป„:

var timers [timersLen]struct {
    timersBucket
    pad [sys.CacheLineSize - unsafe.Sizeof(timersBucket{})%sys.CacheLineSize]byte
}

ๅœจ Go ็š„ๆ—ฉๆœŸๅฎž็Žฐไธญๆ˜ฏๅ…จๅฑ€ไธ€ไธช timer ็š„๏ผŒไฝ†ๆ“ไฝœๅ…จๅฑ€็š„ timer ๅ †่ฆๅŠ ้”๏ผŒๆ‰€ไปฅๅคšๆ ธๅฟƒไผšๆšด้œฒๅ‡บๅ› ไธบไบ‰้”่€Œๆ€ง่ƒฝไฝŽไธ‹็š„้—ฎ้ข˜ใ€‚ไปŽๆŸไธช็‰ˆๆœฌ(ๅ—ฏ๏ผŒๆˆ‘ไนŸไธ็Ÿฅ้“ๅ“ชไธช๏ผŒๅคงๆฆ‚ๆ˜ฏ 1.10)่ตท๏ผŒGo ็š„ timers ไฟฎๆ”นๆˆไบ†่ฟ™็งๅคšไธชๆ—ถ้—ดๅ †็š„ๅฎž็Žฐๆ–นๅผ๏ผŒ็›ฎๅ‰ๅœจ runtime ้‡Œๅ†™ๆญปไธบ 64:

const timersLen = 64

ๅ—ฏ๏ผŒๅฎ˜ๆ–น่กจ็คบๅฆ‚ๆžœๅ’Œ GOMAXPROCS ็›ธ็ญ‰็š„่ฏ๏ผŒ้‚ฃไนˆไผšๅœจ procresize ็š„ๆ—ถๅ€™้‡ๆ–ฐๅˆ†้…ๅ’Œไฟฎๆ”น่ฟ™ไบ›ๆ—ถ้—ดๅ †ใ€‚ๅ†™ๆญปๆˆ 64 ๆ˜ฏๅ†…ๅญ˜ไฝฟ็”จๅ’Œๆ€ง่ƒฝไธŠ็š„ไธ€ไธชๆŠ˜่กทใ€‚ๅฆ‚ๆžœ GOMAXPROCS ๆฏ” 64 ๅคง็š„่ฏ๏ผŒ้‚ฃไนˆๅฏ่ƒฝๅคšไธช P ไผšๅ…ฌ็”จๅŒไธ€ไธชๆ—ถ้—ดๅ †ใ€‚ๅฝ“็„ถ๏ผŒๅฎž้™…ๅœบๆ™ฏไธญๆˆ‘่ฟ˜ๆฒกๆœ‰่ง่ฟ‡ 64 ๆ ธไปฅไธŠ็š„ CPUใ€‚

timers ๆ•ฐ็ป„็š„ๅ…ƒ็ด ๆ˜ฏไธ€ไธชๅŒฟๅ struct๏ผŒๅŒ…ๅซ timersBucket ๅ’Œ pad ไธคไธชๆˆๅ‘˜๏ผŒ่ฟ™ไธช pad ๆ˜ฏไธบไบ†ๅกซๅ…… struct ๅˆฐ cacheline ็š„ๆ•ดๆ•ฐๅ€๏ผŒไปฅ้ฟๅ…ๅœจไธๅŒ็š„ P ไน‹้—ดๅ‘็”Ÿ false sharingใ€‚ๅœจๅคšๆ ธๅฟƒ็š„็ผ–็จ‹ๅœบๆ™ฏไธญ่พƒไธบๅธธ่งใ€‚timerBucket ็š„็ป“ๆž„:

//go:notinheap
type timersBucket struct {
    lock         mutex
    gp           *g
    created      bool
    sleeping     bool
    rescheduling bool
    sleepUntil   int64
    waitnote     note
    t            []*timer
}

ๅ…ถไธญ็š„ t ๅฐฑๆ˜ฏๆˆ‘ไปฌ็š„ๆ—ถ้—ดๅ †ไบ†๏ผŒไธ่ฟ‡่ฟ™ไธชๅ’Œๆˆ‘ไปฌไผ ็ปŸ็š„ heap ็ป“ๆž„็จๅพฎๆœ‰ๆ‰€ไธๅŒ๏ผŒๆ˜ฏๅˆ†ๅ››ไธชๅ‰็š„๏ผŒ่ฟ™็ง่ฎพ่ฎก็ฌฌไธ€ๆฌก่งใ€‚่ฟ™้‡Œ็š„ timersBucket ่ฟ˜ๆœ‰ไธช็‰นๆฎŠ็š„ๆณจ้‡Š go:notinheap๏ผŒๅฎ˜ๆ–น็š„่ฏดๆ˜Ž:

go:notinheap applies to type declarations. It indicates that a type must never be allocated from the GC'd heap. Specifically, pointers to this type must always fail the runtime.inheap check. The type may be used for global variables, for stack variables, or for objects in unmanaged memory (e.g., allocated with sysAlloc, persistentalloc, fixalloc, or from a manually-managed span). Specifically:

  1. new(T), make([]T), append([]T, ...) and implicit heap allocation of T are disallowed. (Though implicit allocations are disallowed in the runtime anyway.)
  2. A pointer to a regular type (other than unsafe.Pointer) cannot be converted to a pointer to a go:notinheap type, even if they have the same underlying type.
  3. Any type that contains a go:notinheap type is itself go:notinheap. Structs and arrays are go:notinheap if their elements are. Maps and channels of go:notinheap types are disallowed. To keep things explicit, any type declaration where the type is implicitly go:notinheap must be explicitly marked go:notinheap as well.
  4. Write barriers on pointers to go:notinheap types can be omitted. The last point is the real benefit of go:notinheap. The runtime uses it for low-level internal structures to avoid memory barriers in the scheduler and the memory allocator where they are illegal or simply inefficient. This mechanism is reasonably safe and does not compromise the readability of the runtime.

ๅ—ฏ๏ผŒไบ†่งฃไธ€ไธ‹ๅฐฑ่กŒไบ†๏ผŒๅœจ็”จๆˆทไปฃ็ ไธญๅŸบๆœฌไธไผš็”จๅพ—ๅˆฐใ€‚

ๅ››ๅ‰ๅฐ้กถๅ †ๆ€ง่ดจ

ๅ››ๅ‰ๅ †้ซ˜ๅบฆไธŠๆฏ”ไบŒๅ‰ๅ †่ฆ็Ÿฎไธ€ไบ›ใ€‚ไธ€ไธช่Š‚็‚น็š„ๆ‰€ๆœ‰(ๆœ€ๅคšๆœ‰4ไธช)ๅญฉๅญ่Š‚็‚น้ƒฝๆฏ”่ฟ™ไธช่Š‚็‚น่ฆๅคงใ€‚ไธ€ไธช่Š‚็‚น็š„(ๅชๆœ‰ไธ€ไธช)็ˆถ่Š‚็‚นไธ€ๅฎšๆฏ”ๅฝ“ๅ‰่Š‚็‚นๅฐใ€‚ไธ‹้ขๆ˜ฏๅกซๅฅฝๅ€ผไน‹ๅŽ็š„ไธ€ไธชๅ…ธๅž‹็š„ๅ››ๅ‰ๅ †:

                                                             โ”Œโ”€โ”€โ”€โ”€โ”€โ”                                                         
                                                             โ”‚     โ”‚                                                         
                                                             โ”‚  0  โ”‚                                                         
                                                             โ””โ”€โ”€โ”€โ”€โ”€โ”˜                                                         
                                                                โ”‚                                                            
                                                                โ”‚                                                            
                                                                โ”‚                                                            
                                                                โ–ผ                                                            
                                                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”                                                
                                                    โ”‚     โ”‚     โ”‚     โ”‚     โ”‚                                                
                                                    โ”‚  3  โ”‚  2  โ”‚  2  โ”‚  10 โ”‚                                                
                                                    โ””โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜                                                
                                                       โ”‚     โ”‚     โ”‚     โ”‚                                                   
                                                       โ”‚     โ”‚     โ”‚     โ”‚                                                   
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                       โ”‚     โ”‚     โ”‚     โ”‚                                                   
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค  4*i+1   โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ”‚     โ”‚     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                     
   โ”‚                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”                               โ”‚                     
   โ”‚                                     โ”‚                             โ”‚                               โ”‚                     
   โ”‚                                     โ”‚                             โ”‚                               โ”‚                     
   โ–ผ                                     โ”‚                             โ”‚                               โ–ผ                     
โ”Œโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”                โ”‚                             โ”‚                            โ”Œโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”
โ”‚     โ”‚     โ”‚     โ”‚     โ”‚                โ–ผ                             โ–ผ                            โ”‚     โ”‚     โ”‚     โ”‚     โ”‚
โ”‚  20 โ”‚  4  โ”‚  5  โ”‚  13 โ”‚             โ”Œโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”       โ”‚ 99  โ”‚ 13  โ”‚ 11  โ”‚  12 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜             โ”‚     โ”‚     โ”‚     โ”‚     โ”‚     โ”‚     โ”‚     โ”‚     โ”‚     โ”‚       โ””โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜
                                      โ”‚ 12  โ”‚ 14  โ”‚ 15  โ”‚  16 โ”‚     โ”‚ 3   โ”‚ 10  โ”‚ 3   โ”‚  3  โ”‚                                
                                      โ””โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜                                

ๅ’ŒไบŒๅ‰ๅ †ไธ€ๆ ท๏ผŒๅฏนไบŽไธ€ไธช่Š‚็‚น็š„่ฆๆฑ‚ๅชๆœ‰ๅ’Œๅ…ถ็ˆถ่Š‚็‚นไปฅๅŠๅญ่Š‚็‚นไน‹้—ด็š„ๅคงๅฐๅ…ณ็ณปใ€‚็›ธ้‚ป่Š‚็‚นไน‹้—ดๆฒกๆœ‰ไปปไฝ•ๅ…ณ็ณปใ€‚

ๆ—ถ้—ดๅ †ๆ’ๅ…ฅ

// ๅˆ†้… timerBucket
// ๅŠ ้”๏ผŒๆทปๅŠ  timer ่ฟ›ๆ—ถ้—ดๅ †
func addtimer(t *timer) {
    tb := t.assignBucket()
    lock(&tb.lock)
    tb.addtimerLocked(t)
    unlock(&tb.lock)
}

// ๅคช็ฎ€ๅ•ไบ†๏ผŒๅฐฑๆ˜ฏ็”จ g.m.p ็š„ id ๆจก 64
// ็„ถๅŽๅˆ†้…ๅฏนๅบ”็š„ timerBucket
func (t *timer) assignBucket() *timersBucket {
    id := uint8(getg().m.p.ptr().id) % timersLen
    t.tb = &timers[id].timersBucket
    return t.tb
}

// ๅ‘ๆ—ถ้—ดๅ †ไธญๆทปๅŠ ไธ€ไธช timer๏ผŒๅฆ‚ๆžœๆ—ถ้—ดๅ †็ฌฌไธ€ๆฌก่ขซๅˆๅง‹ๅŒ–ๆˆ–่€…ๅฝ“ๅ‰็š„ timer ๆฏ”ไน‹ๅ‰ๆ‰€ๆœ‰็š„ timers ้ƒฝ่ฆๆ—ฉ๏ผŒ้‚ฃไนˆๅฐฑๅฏๅŠจ(้ฆ–ๆฌกๅˆๅง‹ๅŒ–)ๆˆ–ๅ”ค้†’(ๆœ€ๆ—ฉ็š„ timer) timerproc
// ๅ‡ฝๆ•ฐๅ†…ๅ‡่ฎพๅค–้ƒจๅทฒ็ปๅฏน timers ๆ•ฐ็ป„ๅŠ ้”ไบ†
func (tb *timersBucket) addtimerLocked(t *timer) {
    // when ๅฟ…้กปๅคงไบŽ 0๏ผŒๅฆๅˆ™ไผšๅœจ่ฎก็ฎ— delta ็š„ๆ—ถๅ€™ๆบขๅ‡บๅนถๅฏผ่‡ดๅ…ถๅฎƒ็š„ runtime timer ๆฐธ่ฟœๆฒกๆณ•่ฟ‡ๆœŸ
    if t.when < 0 {
        t.when = 1<<63 - 1
    }
    t.i = len(tb.t)
    tb.t = append(tb.t, t)
    siftupTimer(tb.t, t.i)
    if t.i == 0 {
        // ๆ–ฐๆ’ๅ…ฅ็š„ timer ๆฏ”ไน‹ๅ‰ๆ‰€ๆœ‰็š„้ƒฝ่ฆๆ—ฉ
        // ๅ‘ไธŠ่ฐƒๆ•ดๅ †
        if tb.sleeping {
            // ไฟฎๆ”น timerBucket ็š„ sleep ็Šถๆ€
            tb.sleeping = false
            // ๅ”ค้†’ timerproc
            // ไฝฟ timerproc ไธญ็š„ for ๅพช็Žฏไธๅ†้˜ปๅกžๅœจ notesleepg ไธŠ
            notewakeup(&tb.waitnote)
        }
        // ๅŒไธ€ไธช P ไธŠ็š„ๆ‰€ๆœ‰ timers ๅฆ‚ๆžœ
        // ้ƒฝๅœจ timerproc ไธญ่ขซๅผนๅ‡บไบ†
        // ่ฏฅ rescheduling ไผš่ขซๆ ‡่ฎฐไธบ true
        // ๅนถไธ”ๅฏๅŠจ timerproc ็š„ goroutine ไผš่ขซ goparkunlock
        if tb.rescheduling {
            // ่ฏฅๆ ‡่ฎฐไผšๅœจ่ฟ™้‡Œๅ’Œ timejumpLocked ไธญ่ขซ่ฎพ็ฝฎไธบ false
            tb.rescheduling = false
            goready(tb.gp, 0)
        }
    }
    // ๅฆ‚ๆžœ timerBucket ๆ˜ฏ็ฌฌไธ€ๆฌกๅˆ›ๅปบ๏ผŒ้œ€่ฆๅฏๅŠจไธ€ไธช goroutine
    // ๆฅๅพช็Žฏๅผนๅ‡บๆ—ถ้—ดๅ †๏ผŒๅ†…้ƒจไผšๆ นๆฎ้œ€่ฆๆœ€ๆ—ฉ่งฆๅ‘็š„ timer
    // ่ฟ›่กŒ็›ธๅบ”ๆ—ถ้—ด็š„ sleep
    if !tb.created {
        tb.created = true
        go timerproc(tb)
    }
}

ๆ’ๅ…ฅ timer ๅˆฐๅ †ไธญ็š„ๆ—ถๅ€™็š„้€ป่พ‘ๆ˜ฏๅ…ˆ่ฟฝๅŠ ๅˆฐๆ•ฐ็ป„ๆœซๅฐพ(append)๏ผŒ็„ถๅŽๅ‘ไธŠ adjust(siftup) heap ไปฅ้‡ๆ–ฐๆขๅคๅ››ๅ‰ๅฐ้กถๅ †ๆ€ง่ดจใ€‚

ๆ—ถ้—ดๅ †ๅˆ ้™ค

// ไปŽๅ †ไธญๅˆ ้™ค timer t
// ๅฆ‚ๆžœ timerproc ๆๅ‰่ขซๅ”ค้†’ไนŸๆฒกๆ‰€่ฐ“
func deltimer(t *timer) bool {
    if t.tb == nil {
        // t.tb can be nil if the user created a timer
        // directly, without invoking startTimer e.g
        //    time.Ticker{C: c}
        // In this case, return early without any deletion.
        // See Issue 21874.
        return false
    }

    tb := t.tb

    lock(&tb.lock)
    // t may not be registered anymore and may have
    // a bogus i (typically 0, if generated by Go).
    // Verify it before proceeding.
    i := t.i
    last := len(tb.t) - 1
    if i < 0 || i > last || tb.t[i] != t {
        unlock(&tb.lock)
        return false
    }
    // ๆŠŠ timer[i] ๆ›ฟๆขไธบ timer[last]
    if i != last {
        tb.t[i] = tb.t[last]
        tb.t[i].i = i
    }
    // ๅˆ ้™ค timer[last]๏ผŒๅนถ็ผฉๅฐ slice
    tb.t[last] = nil
    tb.t = tb.t[:last]

    // ๅˆคๆ–ญๆ˜ฏไธๆ˜ฏๅˆ ็š„ๆœ€ๅŽไธ€ไธช
    // ๅฆ‚ๆžœไธๆ˜ฏ็š„่ฏ๏ผŒ้œ€่ฆ้‡ๆ–ฐ่ฐƒๆ•ดๅ †
    if i != last {
        // ๆœ€ๅŽไธ€ไธช่Š‚็‚นๅฝ“ๅ‰ๆฅ็š„ๅˆ†ๅ‰ๅฏ่ƒฝๅนถไธๆ˜ฏๅฎƒ้‚ฃไธชๅˆ†ๅ‰
        // ๆ‰€ไปฅๅ‘ไธŠ่ตฐๆˆ–่€…ๅ‘ไธ‹่ตฐ้ƒฝๆ˜ฏๆœ‰ๅฏ่ƒฝ็š„
        // ๅณไฝฟๆ˜ฏไบŒๅ‰ๅ †๏ผŒไนŸๆ˜ฏๆœ‰่ฟ™็งๅฏ่ƒฝ็š„
        siftupTimer(tb.t, i)
        siftdownTimer(tb.t, i)
    }
    unlock(&tb.lock)
    return true
}

timer ่งฆๅ‘

// timerproc ่ดŸ่ดฃๅค„็†ๆ—ถ้—ด้ฉฑๅŠจ็š„ไบ‹ไปถ
// ๅœจๅ †ไธญ็š„ไธ‹ไธ€ไธชไบ‹ไปถ้œ€่ฆ่งฆๅ‘ไน‹ๅ‰๏ผŒไผšไธ€็›ดไฟๆŒ sleep ็Šถๆ€
// ๅฆ‚ๆžœ addtimer ๆ’ๅ…ฅไบ†ไธ€ไธชๆ›ดๆ—ฉ็š„ไบ‹ไปถ๏ผŒไผšๆๅ‰ๅ”ค้†’ timerproc
func timerproc(tb *timersBucket) {
    tb.gp = getg()
    for {
        // timerBucket ็š„ๅฑ€้ƒจๅคง้”
        lock(&tb.lock)
        // ่ขซๅ”ค้†’๏ผŒๆ‰€ไปฅไฟฎๆ”น sleeping ็Šถๆ€ไธบ false
        tb.sleeping = false
        // ่ฎกๆ—ถ
        now := nanotime()
        delta := int64(-1)
        // ๅœจๅค„็†ๅฎŒๅˆฐๆœŸ็š„ timer ไน‹ๅ‰๏ผŒไธ€็›ดๅพช็Žฏ
        for {
            // ๅฆ‚ๆžœ timer ๅทฒ็ป้ƒฝๅผนๅ‡บไบ†
            // ้‚ฃไนˆไธ็”จๅพช็Žฏไบ†๏ผŒ่ทณๅ‡บๅŽๆŽฅ็€็ก่ง‰
            if len(tb.t) == 0 {
                delta = -1
                break
            }
            // ๅ–ๅฐ้กถๅ †้กถ้ƒจๅ…ƒ็ด 
            // ๅณๆœ€่ฟ‘ไผš่ขซ่งฆๅ‘็š„ timer
            t := tb.t[0]
            delta = t.when - now // ่ฟ˜ๅทฎๅคš้•ฟๆ—ถ้—ดๆ‰้œ€่ฆ่งฆๅ‘ๆœ€่ฟ‘็š„ timer
            if delta > 0 {
                // ๅคงไบŽ 0 ่ฏดๆ˜Ž่ฟ™ไธช timer ่ฟ˜ๆฒกๅˆฐ้œ€่ฆ่งฆๅ‘็š„ๆ—ถ้—ด
                // ่ทณๅ‡บๅพช็ŽฏๅŽป็ก่ง‰
                break
            }
            if t.period > 0 {
                // ่ฟ™ไธช timer ่ฟ˜ไผš็•™ๅœจๅ †้‡Œ
                // ไธ่ฟ‡่ฆ่ฐƒๆ•ดๅฎƒ็š„ไธ‹ๆฌก่งฆๅ‘ๆ—ถ้—ด
                t.when += t.period * (1 + -delta/t.period)
                siftdownTimer(tb.t, 0)
            } else {
                // ไปŽๅ †ไธญ็งป้™ค่ฟ™ไธช timer
                // ็”จๆœ€ๅŽไธ€ไธช timer ่ฆ†็›–็ฌฌ 0 ไธช timer
                // ็„ถๅŽๅ‘ไธ‹่ฐƒๆ•ดๅ †
                last := len(tb.t) - 1
                if last > 0 {
                    tb.t[0] = tb.t[last]
                    tb.t[0].i = 0
                }
                tb.t[last] = nil
                tb.t = tb.t[:last]
                if last > 0 {
                    siftdownTimer(tb.t, 0)
                }
                t.i = -1 // ๆ ‡่ฎฐ timer ๅœจๅ †ไธญ็š„ไฝ็ฝฎๅทฒ็ปๆฒกๆœ‰ไบ†
            }
            // timer ่งฆๅ‘ๆ—ถ้œ€่ฆ่ฐƒ็”จ็š„ๅ‡ฝๆ•ฐ
            f := t.f
            arg := t.arg
            seq := t.seq
            unlock(&tb.lock)
            // ่ฐƒ็”จ้œ€่งฆๅ‘็š„ๅ‡ฝๆ•ฐ
            f(arg, seq)
            // ๆŠŠ้”ๅŠ ๅ›žๆฅ๏ผŒๅฆ‚ๆžœไธ‹ๆฌก break ไบ†ๅ†…ๅฑ‚็š„ for ๅพช็Žฏ
            // ่ƒฝไฟ่ฏ timeBucket ๆ˜ฏ่ขซ้”ไฝ็š„
            // ็„ถๅŽๅœจไธ‹้ข็š„ goparkunlock ไธญ่ขซ่งฃ้”
            lock(&tb.lock)
        }
        if delta < 0 || faketime > 0 {
            // ่ฏดๆ˜Žๆ—ถ้—ดๅ †้‡Œๅทฒ็ปๆฒกๆœ‰ timer ไบ†
            // ่ฎฉ goroutine ๆŒ‚่ตท๏ผŒๅŽป็ก่ง‰
            tb.rescheduling = true
            goparkunlock(&tb.lock, "timer goroutine (idle)", traceEvGoBlock, 1)
            continue
        }
        // ่ฏดๆ˜Žๅ †้‡Œ่‡ณๅฐ‘่ฟ˜ๆœ‰ไธ€ไธชไปฅไธŠ็š„ timer
        // ็กๅˆฐๆœ€่ฟ‘็š„ timer ๆ—ถ้—ด
        tb.sleeping = true
        tb.sleepUntil = now + delta
        noteclear(&tb.waitnote)
        unlock(&tb.lock)
        // ๅ†…้ƒจๆ˜ฏ futex sleep
        // ๆ—ถ้—ด็กๅˆฐไบ†ไผš่‡ชๅŠจ้†’
        // ๆˆ–่€… addtimer ็š„ๆ—ถๅ€™๏ผŒๅ‘็Žฐๆ–ฐ็š„ timer ๆ›ดๆ—ฉ๏ผŒไผšๆๅ‰ๅ”ค้†’
        notetsleepg(&tb.waitnote, delta)
    }
}

ๅฏไปฅ็•™ๆ„ไธ€ไธ‹่ฟ™้‡Œ็š„ period๏ผŒๆœ‰ period ็š„ timer ไผšไปŽ when ๅผ€ๅง‹๏ผŒๆฏ้š” period ๆฎตๆ—ถ้—ด๏ผŒๅฐฑๅ†ๆฌก่งฆๅ‘ใ€‚

                                                                                
                                          when+period                           
                                                          when+period*3         
                                             โ”‚                                  
                                             โ”‚               โ”‚                  
                                             โ”‚               โ”‚                  
                                             โ”‚  when+period*2โ”‚                  
                                  when       โ”‚               โ”‚                  
                                             โ”‚       โ”‚       โ”‚                  
                                     โ”‚       โ”‚       โ”‚       โ”‚        .....     
                                     โ”‚       โ”‚       โ”‚       โ”‚                  
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                        โ”‚       โ”‚       โ”‚       โ”‚                  
โ”‚ timeline  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ท
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                        โ”‚       โ”‚       โ”‚       โ”‚                  
                                     โ–ผ       โ–ผ       โ–ผ       โ–ผ                  
                                                                                
                                  trigger          trigger                      
                                          trigger          trigger              

ๆ—ถ้—ดๅ †่ฐƒๆ•ด

ไน‹ๅ‰็š„ไปฃ็ ไนŸ็œ‹ๅˆฐไบ†๏ผŒๆ—ถ้—ดๅ †่ฐƒๆ•ดๆœ‰ๅ‘ไธŠ่ฐƒๆ•ดๅ’Œๅ‘ไธ‹่ฐƒๆ•ดไธค็ง่ฐƒๆ•ดๆ–นๅผใ€‚

ๅ‘ไธŠ่ฐƒๆ•ด

func siftupTimer(t []*timer, i int) {
    // ๅ…ˆๆš‚ๅญ˜ๅฝ“ๅ‰ๅˆšๆ’ๅ…ฅๅˆฐๆ•ฐ็ป„ๅฐพ้ƒจ็š„่Š‚็‚น
    when := t[i].when
    tmp := t[i]

    // ไปŽๅฝ“ๅ‰ๆ’ๅ…ฅ่Š‚็‚น็š„็ˆถ่Š‚็‚นๅผ€ๅง‹
    // ๅฆ‚ๆžœๆœ€ๆ–ฐๆ’ๅ…ฅ็š„้‚ฃไธช่Š‚็‚น็š„่งฆๅ‘ๆ—ถ้—ด่ฆๆฏ”็ˆถ่Š‚็‚น็š„่งฆๅ‘ๆ—ถ้—ดๆ›ดๆ—ฉ
    // ้‚ฃไนˆๅฐฑๆŠŠ่ฟ™ไธช็ˆถ่Š‚็‚นไธ‹็งป
    for i > 0 {
        p := (i - 1) / 4 // parent
        if when >= t[p].when {
            break
        }
        t[i] = t[p]
        t[i].i = i
        i = p
    }

    // ๅฆ‚ๆžœๅ‘็”Ÿ่ฟ‡็งปๅŠจ๏ผŒ็”จๆœ€ๆ–ฐๆ’ๅ…ฅ็š„่Š‚็‚น
    // ่ฆ†็›–ๆŽ‰ๆœ€ๅŽไธ€ไธชไธ‹็งป็š„็ˆถ่Š‚็‚น
    if tmp != t[i] {
        t[i] = tmp
        t[i].i = i
    }
}

ๅ‘ไธ‹่ฐƒๆ•ด

func siftdownTimer(t []*timer, i int) {
    n := len(t)
    when := t[i].when
    tmp := t[i]
    for {
        c := i*4 + 1 // ๆœ€ๅทฆๅญฉๅญ่Š‚็‚น
        c3 := c + 2  // ็ฌฌไธ‰ไธชๅญฉๅญ่Š‚็‚น
        if c >= n {
            break
        }
        w := t[c].when
        if c+1 < n && t[c+1].when < w {
            w = t[c+1].when
            c++
        }
        if c3 < n {
            w3 := t[c3].when
            if c3+1 < n && t[c3+1].when < w3 {
                w3 = t[c3+1].when
                c3++
            }
            if w3 < w {
                w = w3
                c = c3
            }
        }
        if w >= when {
            break
        }
        t[i] = t[c]
        t[i].i = i
        i = c
    }
    if tmp != t[i] {
        t[i] = tmp
        t[i].i = i
    }
}

่ฟ™ๆฎตไปฃ็ ๅฎžๅœจๆ˜ฏ็งฐไธไธŠไผ˜้›…๏ผŒๅ…ถๅฎžๅฐฑๆ˜ฏๅœจๆ‰€ๆœ‰ๅญฉๅญ่Š‚็‚นไธญๅ…ˆๆ‰พๅ‡บๆœ€ๅฐ็š„้‚ฃไธ€ไธช๏ผŒๅฆ‚ๆžœๆœ€ๅฐ็š„ๆฏ”ๅฝ“ๅ‰่ฆไธ‹็งป็š„่Š‚็‚น่ฟ˜่ฆๅคง๏ผŒ้‚ฃไนˆๅฐฑ breakใ€‚ๅไน‹๏ผŒๅˆ™ๅฐ†ๆœ€ๅฐ็š„่Š‚็‚นไธŠ็งป๏ผŒ็„ถๅŽๅ†ๅˆคๆ–ญ่ฟ™ไธชๆœ€ๅฐ่Š‚็‚น็š„ 4 ไธชๅญ่Š‚็‚นๆ˜ฏๅฆ้ƒฝๆฏ”่ฆไธ‹็งป็š„่Š‚็‚นๅคงใ€‚ไปฅๆญค็ฑปๆŽจใ€‚็”จๅ›พๆฅๆจกๆ‹Ÿไธ€ไธ‹่ฟ™ไธช่ฟ‡็จ‹:

                         โ”‚            โ”Œโ”€โ”€โ”€โ”                                       
                         โ”‚            โ”‚ 5 โ”‚                                       
                         โ”‚            โ””โ”€โ”€โ”€โ”˜                                       
                         โ”‚              โ”‚                                         
                         โ”‚        โ”Œโ”€โ”€โ”€โ”€โ”€โ”˜                                         
                         โ”‚        โ–ผ                                               
                         โ”‚      โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ณโ”โ”โ”โ”ณโ”€โ”€โ”€โ”                                 
                         โ”‚      โ”‚ 7 โ”‚ 3 โ”‚ 2 โ”ƒ 6 โ”‚                                 
                         โ”‚      โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ปโ”โ”โ”โ”ปโ”€โ”€โ”€โ”˜                                 
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚                โ”‚                                       
โ”‚   siftdownTimer   โ”‚    โ”‚                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                            
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚                           โ–ผ                            
     .โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€.         โ”‚                         โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ณโ”โ”โ”โ”“              
    (  before   )        โ”‚                         โ”‚ 4 โ”‚ 5 โ”‚ 9 โ”‚ 3 โ”ƒ              
     `โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'         โ”‚                         โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ปโ”โ”โ”โ”›              
                         โ”‚                                       โ”‚                
                         โ”‚                                       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  
                         โ”‚                                                     โ–ผ  
                         โ”‚                                       โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ณโ”โ”โ”โ”“
                         โ”‚                                       โ”‚ 6 โ”‚ 6 โ”‚ 6 โ”‚ 4 โ”ƒ
                         โ”‚                                       โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ปโ”โ”โ”โ”›
                         โ”‚                                                        
                         โ–ผ                                                        
                                                                                  
                                                                                  
                                                                                  
                         โ”‚            โ”Œโ”€โ”€โ”€โ”                                       
                         โ”‚            โ”‚ 2 โ”‚                                       
                         โ”‚            โ””โ”€โ”€โ”€โ”˜                                       
                         โ”‚              โ”‚                                         
                         โ”‚        โ”Œโ”€โ”€โ”€โ”€โ”€โ”˜                                         
                         โ”‚        โ–ผ                                               
                         โ”‚      โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ณโ”โ”โ”โ”ณโ”€โ”€โ”€โ”                                 
                         โ”‚      โ”‚ 7 โ”‚ 3 โ”‚ 3 โ”ƒ 6 โ”‚                                 
                         โ”‚      โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ปโ”โ”โ”โ”ปโ”€โ”€โ”€โ”˜                                 
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚                โ”‚                                       
โ”‚   siftdownTimer   โ”‚    โ”‚                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                            
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚                           โ–ผ                            
    .โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€.          โ”‚                         โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ณโ”โ”โ”โ”“              
   (   after   )         โ”‚                         โ”‚ 4 โ”‚ 5 โ”‚ 9 โ”‚ 4 โ”ƒ              
    `โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€'          โ”‚                         โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ปโ”โ”โ”โ”›              
                         โ”‚                                       โ”‚                
                         โ”‚                                       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  
                         โ”‚                                                     โ–ผ  
                         โ”‚                                       โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ณโ”โ”โ”โ”“
                         โ”‚                                       โ”‚ 6 โ”‚ 6 โ”‚ 6 โ”‚ 5 โ”ƒ
                         โ”‚                                       โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ปโ”โ”โ”โ”›
                         โ”‚                                                        
                         โ–ผ                                                        

ๆต็จ‹

timer.After ๆต็จ‹

func After(d Duration) <-chan Time {
    return NewTimer(d).C
}

// NewTimer creates a new Timer that will send
// the current time on its channel after at least duration d.
func NewTimer(d Duration) *Timer {
    c := make(chan Time, 1)
    t := &Timer{
        C: c,
        r: runtimeTimer{
            when: when(d),
            f:    sendTime,
            arg:  c,
        },
    }
    startTimer(&t.r)
    return t
}

func startTimer(*runtimeTimer)

่ฟ™ไธช startTimer ็š„ๅฎž็Žฐๆ˜ฏๅœจ runtime/time.go ้‡Œ:

// startTimer adds t to the timer heap.
// ๆŠŠ t ๆทปๅŠ ๅˆฐ timer ๅ †
//go:linkname startTimer time.startTimer
func startTimer(t *timer) {
    addtimer(t)
}

addtimer ๅŽ้ข็š„ๆต็จ‹ไน‹ๅ‰ๅทฒ็ป็œ‹่ฟ‡ไบ†ใ€‚

timer.Tick ๆต็จ‹

func Tick(d Duration) <-chan Time {
    if d <= 0 {
        return nil
    }
    return NewTicker(d).C
}
// NewTicker ไผš่ฟ”ๅ›žไธ€ไธช Ticker ๅฏน่ฑก๏ผŒๅ…ถ channel ๆฏ้š” period ๆ—ถ้—ด
// ไผšๆ”ถๅˆฐไธ€ไธชๆ—ถ้—ดๅ€ผ
// ๅฆ‚ๆžœ receiver ๆŽฅๆ”ถๆ…ขไบ†๏ผŒTicker ไผšๆŠŠไธ้œ€่ฆ็š„ tick drop ๆŽ‰
// d ๅฟ…้กปๆฏ” 0 ๅคง๏ผŒๅฆๅˆ™ panic
// Stop ticker ๆ‰่ƒฝ้‡Šๆ”พ็›ธๅ…ณ็š„่ต„ๆบ
func NewTicker(d Duration) *Ticker {
    if d <= 0 {
        panic(errors.New("non-positive interval for NewTicker"))
    }
    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
}

ๅฏไปฅ็œ‹ๅˆฐ๏ผŒ Ticker ๅ’Œ Timer ็š„ r ๆˆๅ‘˜ๅฐฑๅชๅทฎๅœจ period ่ฟ™ไธ€ไธชๅญ—ๆฎตไธŠ๏ผŒๆฏ้š”ไธ€ไธช period ๅฐฑๅพ€ channel ้‡Œๅ‘ๆ•ฐๆฎ็š„ๅฐฑๆ˜ฏ Ticker๏ผŒ่€Œ fire and disappear ็š„ๅฐฑๆ˜ฏ Timerใ€‚

Stop ๆต็จ‹

func (t *Ticker) Stop() {
    stopTimer(&t.r)
}

func (t *Timer) Stop() bool {
    if t.r.f == nil {
        panic("time: Stop called on uninitialized Timer")
    }
    return stopTimer(&t.r)
}

Timer ๅ’Œ Ticker ้ƒฝๆ˜ฏ่ฐƒ็”จ็š„ stopTimerใ€‚

func stopTimer(t *timer) bool {
    return deltimer(t)
}

deltimer ๅœจไธŠ้ขไนŸ็œ‹ๅˆฐ่ฟ‡ไบ†ใ€‚

Reset ๆต็จ‹

func (t *Timer) Reset(d Duration) bool {
    if t.r.f == nil {
        panic("time: Reset called on uninitialized Timer")
    }
    w := when(d)
    active := stopTimer(&t.r)
    t.r.when = w
    startTimer(&t.r)
    return active
}

้ƒฝๆ˜ฏ่ง่ฟ‡็š„ๅ‡ฝๆ•ฐ๏ผŒๆฒกๅ•ฅ็‰นๅˆซ็š„ใ€‚

ๆœ€ๅŽ

ๆœฌ็ฏ‡ๅ†…ๅฎนไธป่ฆๆ˜ฏ่ฎฒ Go ็š„ๅฎšๆ—ถๅ™จๅฎž็Žฐ๏ผŒๅทฅไธš็•Œ็š„ๅฎšๆ—ถๅ™จๅฎž็Žฐๅนถไธๅชๆœ‰ไธ€็งใ€‚ๅฆ‚ๆžœไฝ ่ฟ˜ๆƒณ็Ÿฅ้“ๅ…ถๅฎƒ็ณป็ปŸ๏ผŒๆฏ”ๅฆ‚ nginx ้‡Œๆ˜ฏๆ€Žไนˆๅฎž็Žฐๅฎšๆ—ถๅ™จ็š„๏ผŒๅฏไปฅๅ‚่€ƒ่ฟ™ไธ€็ฏ‡ใ€‚