Golang では、定期的に発生するイベントを作成するためにティッカー チャネルがよく使用されます。ただし、チャネルを適切に処理するには、Stop() の動作を理解することが重要です。
次のコード スニペットを考えてみましょう。
ticker := time.NewTicker(1 * time.Second) go func() { for _ = range ticker.C { log.Println("tick") } log.Println("stopped") }() time.Sleep(3 * time.Second) log.Println("stopping ticker") ticker.Stop() time.Sleep(3 * time.Second)
ticker.Stop() が呼び出されると、ティッカーは一時停止されていますが、チャンネルは自動的に閉じられません。これは、ゴルーチンは一時停止しますが、終了しないことを意味します。上記のコードを実行すると、次の出力が生成されます。
2013/07/22 14:26:53 tick 2013/07/22 14:26:54 tick 2013/07/22 14:26:55 tick 2013/07/22 14:26:55 stopping ticker
したがって、ゴルーチンはブロックされたままになり、さらなるティッカー イベントを待機します。
この問題を解決するには、2 番目のチャネルを使用して、ティッカーゴルーチンへの停止リクエスト。以下に例を示します。
package main import ( "log" "sync" "time" ) type Ticker struct { sync.Mutex ticker *time.Ticker stop chan struct{} } func (t *Ticker) Start(d time.Duration) { t.Lock() defer t.Unlock() if t.ticker != nil { t.ticker.Stop() } t.ticker = time.NewTicker(d) t.stop = make(chan struct{}) go func() { for { select { case <-t.ticker.C: log.Println("tick") case <-t.stop: return } } }() } func (t *Ticker) Stop() { t.Lock() defer t.Unlock() if t.stop != nil { close(t.stop) t.ticker.Stop() } } func main() { t := Ticker{} t.Start(1 * time.Second) time.Sleep(3 * time.Second) log.Println("stopping ticker") t.Stop() time.Sleep(3 * time.Second) }
別の停止チャネルを使用すると、Ticker.Stop() メソッドが呼び出されたときにティッカー ゴルーチンを適切に終了できます。
以上がTicker.Stop() は Golang でどのように動作するのでしょうか?また、ティッカー ゴルーチンの正常な終了を保証するにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。