赞
踩
项目需要使用信号进行优雅的退出(即主协程在所有协程退出之后再退出)
该问题是预防协程泄露的解决方案之一,下面demo 使用 signal 信号信道,来监测程序是否被信号中断,使用WaitGroup 来等待子协程全部回收后主协程退出,使用ctx + select来传递子协程的退出信号
该问题是预防协程泄露的解决方案之一,下面demo 使用 signal 信号信道,来监测程序是否被信号中断,使用WaitGroup 来等待子协程全部回收后主协程退出,使用ctx + select来传递子协程的退出信号
package main import ( "context" "fmt" "os" "os/signal" "sync" "syscall" "time" ) var gctx = context.Background() var wg sync.WaitGroup // 凌晨定时处理删除任务 func TimeToDelDb(ctx context.Context) { for { now := time.Now() next := now.Add(time.Hour * 24) //通过now偏移24小时 next = time.Date(next.Year(), next.Month(), next.Day(), 0, 0, 0, 0, next.Location()) //获取下一个凌晨的日期 t := time.NewTimer(next.Sub(now)) //计算当前时间到凌晨的时间间隔,设置一个定时器 select { case <-t.C: // 执行删除任务 case <-ctx.Done(): fmt.Println("ctx stop") wg.Done() return } } } func main() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGQUIT) ctx, cancel := context.WithCancel(gctx) wg.Add(2) go TimeToDelDb(ctx) ticker := time.NewTicker(3 * time.Second) // 运行时长 go func() { for { select { case <-ticker.C: // 执行xx任务 case <-sigs: fmt.Println("signal stop") wg.Done() cancel() } } defer ticker.Stop() }() wg.Wait() fmt.Println("Progress stop") }
减少部分不需要的协程
(select 中 使用break只能跳出select 使用return 走不到waitgroup 里面 )
package main import ( "context" "fmt" "os" "os/signal" "sync" "syscall" "time" ) var gctx = context.Background() var wg sync.WaitGroup // 凌晨定时处理删除任务 func TimeToDelDb(ctx context.Context) { for { now := time.Now() next := now.Add(time.Hour * 24) //通过now偏移24小时 next = time.Date(next.Year(), next.Month(), next.Day(), 0, 0, 0, 0, next.Location()) //获取下一个凌晨的日期 t := time.NewTimer(next.Sub(now)) //计算当前时间到凌晨的时间间隔,设置一个定时器 select { case <-t.C: // 执行删除任务 case <-ctx.Done(): fmt.Println("ctx stop") wg.Done() return } } } func main() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGQUIT) ctx, cancel := context.WithCancel(gctx) wg.Add(1) go TimeToDelDb(ctx) ticker := time.NewTicker(3 * time.Second) // 运行时长 for { select { case <-ticker.C: // 执行xx任务 case <-sigs: cancel() fmt.Println("signal stop") goto Exit } } defer ticker.Stop() Exit: wg.Wait() fmt.Println("Progress stop") }
user@dev:~$ go run test.go
^Csignal stop
ctx stop
Progress stop
user@dev:~$
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。