Tickers

Un tickerè simile ad un timer, in quanto allo scatto invia un elemento al suo channel C.
Ma un ticker continua all'infinito a scattare a intervalli regolari.

E' una differenza simile a quella di at e cronin Linux.

Un ticker si crea in memoria dinamica con la funzione NewTicker.

Un ticker è fermabile con la funzione Stop, ma non è più ristartabile.

L'elemento posto sul channel C è un timestamp.

Esempio

(330tickers.go):

package main

import "time"
import "fmt"

func main() {

	// Un ticker ha un channel che riceve un elemento
	// a intervalli regolari
	fmt.Println("main: ticker set every 500 ms")
	ticker := time.NewTicker(time.Millisecond * 500)
	// Goroutine che legge il ticker se pieno
	// oppure conta i secondi
	go func() {
		i := 0
		for {
			select {
			case t := <-ticker.C:
				fmt.Println("go: tick at", t)
			case <- time.After(time.Second):
				i++
				fmt.Printf("go: still here after %d sec\n", i)
			}
		}
	}()

	// I ticker si possono fermare come i timer
	fmt.Println("main: sleeping for 5600 ms")
	time.Sleep(time.Millisecond * 5600)
	ticker.Stop()
	fmt.Println("main: ticker stopped")
	// Fermare un ticker non termina i thread che lo ascoltano
	// Un ticker non si può risettare
	fmt.Println("main: waiting 5 seconds before exiting")
	<-time.After(5 * time.Second)
	fmt.Println("main: exiting now")
}

Anche qui allo stop del ticker tutte le routine che lo leggono continuano ad attendere se non sono informate.

Due goroutine in lettura

Se due goroutine leggono dallo stesso ticker, la prima che arriva legge, l'altra no e perde il turno.

Questo è dimostrato dal programma:

(331-tickers-two.go):

package main

import (
	"fmt"
	"time"
)

func main() {
	ticker := time.NewTicker(time.Second)

	go func() {
		i := 0
		for {
			select {
			case t := <-ticker.C:
				fmt.Println("go1: tick at", t)
			case <-time.After(time.Millisecond * 500):
				i++
				fmt.Printf("go1: still here after %d millisec\n", i*500)
			}
		}
	}()
	go func() {
		i := 0
		for {
			select {
			case t := <-ticker.C:
				fmt.Println("go2: tick at", t)
			case <-time.After(time.Millisecond * 800):
				i++
				fmt.Printf("go2: still here after %d millisec\n", i*800)
			}
		}
	}()

	<-time.After(10 * time.Second)
	fmt.Println("main: exiting now")
}