Timer的使用(延迟执行)

package main

import (
   "fmt"
   "time"
)

var location, _ = time.LoadLocation("Asia/Shanghai")
var layout = "2006-01-02 15:04:05"

// GetDateTime 获取当前时间的日期时间字符串
// @return string 日期时间字符串
func GetDateTime() string {
   sec := time.Now().In(location).Unix()
   return time.Unix(sec, 0).In(location).Format(layout)
}

func main() {
   timer := time.NewTimer(time.Second * 3) // 创建Timer,设置3秒后执行,这里并不会发生阻塞。

   fmt.Printf("[%+v] 等待执行 \n", GetDateTime())

   // 停止并重置Timer
   if !timer.Stop() {
      <-timer.C // 清空管道(Timer的管道长度为1,只要读出数据就是清空了)
   }
   timer.Reset(time.Second * 3)

   channel := <-timer.C // 重要提醒:这里会发生阻塞,阻塞时间长短由设置的延迟时间决定。
   fmt.Printf("[%+v] 正在执行 \n", channel.In(location).Format(layout))
   time.Sleep(time.Second * 2)

   fmt.Printf("[%+v] 完成执行 \n", GetDateTime())
}

//========== 总结 ==========//
// 1、Go里的Timer相当于JavaScript里的setTimeout(),就是把一些任务延迟执行,例如订单状态的变更,如果用户一直没有支付,订单不
//    可能一直保持在待支付状态,肯定需要在过了一定时间后将订单状态改为已失效,这时就可以使用Timer,具体做法就是在创建订单的
//    同时创建对应的Timer来延迟更新订单状态,如果超时了用户仍未支付就将订单状态改为已失效。
// 2、Timer的本质是管道的读写,time.NewTimer()就是把执行任务时间(延迟)写入管道,开发者从管道读到数据后实现自己的逻辑即可。
// 3、Timer提供了Stop()方法和Reset()方法来实现停止和重置,两者一般配对使用避免出现deadlock问题。
// 4、如果调用timer.Stop()停止了Timer还从timer.C管道读取数据就会发生deadlock。

Copyright © 2024 码农人生. All Rights Reserved