併發技術3:定時器

尹成發表於2018-11-16

定時器概述

  • Go為我們提供了兩種不同方式的計時器:
  • 定時執行任務的計時器
  • 週期性執行任務的計時器

固定時間定時器
下面的例子演示瞭如何使用定時器延時2秒執行一項任務

func main() {
	//建立2秒的定時器
	timer := time.NewTimer(2*time.Second)
	//當前時間: 2018-09-25 19:17:16.8050379 +0800 CST m=+0.004010601
	fmt.Println("當前時間:", time.Now())

	//2秒後,從單向時間管道中讀出內容(當前時間)
	//timer.C是一個單向的時間管道
	t := <-timer.C
	//t =  2018-09-25 19:17:18.8051013 +0800 CST m=+2.004074101
	fmt.Println("t = ", t)
}

上面的例子還可以寫作

func main() {
	fmt.Println("開始計時")
	
	//建立2秒的定時器,得到其單向輸出時間管道,阻塞2秒後讀出時間資料
	<- time.After(2 * time.Second)
	fmt.Println("時間到")
}

提前終止計時器
下面的例子中,計時器被中途stop掉了,被延時的協程將永遠得不到執行

func main() {
	//建立3秒的定時器,3秒
	timer := time.NewTimer(3 * time.Second)

	//3秒後從定時器時間管道中讀取時間
	//這裡子協程永遠得不到執行,因為後面的程式碼會停掉這個計時器
	go func() {
		<-timer.C
		fmt.Println("子協程可以列印了,因為定時器的時間到了")
	}()

	//停止定時器,停止狀態下,計時器失效,被timer.C所阻塞的協程永遠讀不出資料
	timer.Stop()

	//主協程為子協程留出足夠的執行時間
	time.Sleep(6*time.Second)
	fmt.Println("GAME OVER")
}

中途重置定時器

  • 下面的例子中,timer在配置為延時10秒執行後,又被重置為1秒,所以其實際延時1秒
  • 需要注意的是,如果在reset的一剎那,定時器已經到時或者已被stop掉,則reset是無效的
func main() {
	//建立3秒的定時器
	timer := time.NewTimer(10 * time.Second)

	//重置為1秒
	//如果已經到時,或者已經Stop掉,則重置失敗
	ok := timer.Reset(1 * time.Second)
	fmt.Println("ok = ", ok, time.Now())

	//1秒後即可讀出時間
	t := <-timer.C
	fmt.Println("時間到", t)
}

週期性執行的定時器
下面的例子將每隔一秒輸出一次當前時間,5次後程式結束

func main() {
	//建立1秒的秒錶
	ticker := time.NewTicker(1 * time.Second)
	//ticker := mytime.NewTimer(1 * mytime.Second)

	i := 0
	for {
		//從秒錶的管道中讀出時間
		t := <-ticker.C
		i++
		fmt.Println("i = ", i, t)

		//停止秒錶
		if i == 5 {
			ticker.Stop()
			break
		}
	}

	fmt.Println("Game Over")
}

學院Go語言視訊主頁
https://edu.csdn.net/lecturer/1928

清華團隊帶你實戰區塊鏈開發
掃碼獲取海量視訊及原始碼 QQ群:721929980
在這裡插入圖片描述

相關文章