话不多说,先贴代码
package main import ( "time" "os" "os/signal" "fmt" "syscall" "sync" ) type Task struct { closed chan struct{} wg sync.WaitGroup ticker *time.Ticker } func (t *Task) Stop() { close(t.closed) } func (t *Task) Run(i int) { fmt.Println("start id =",i) for { select { case value,ok :=<-t.closed: fmt.Println("get closed value=", value,"ok=",ok) return case <-t.ticker.C: handle() } } } func handle() { for i := 0; i < 25; i++ { fmt.Print("#") time.Sleep(time.Millisecond * 200) } fmt.Println() } func main() { task := &Task{ closed: make(chan struct{}), ticker: time.NewTicker(time.Second * 6), } c := make(chan os.Signal) signal.Notify(c, syscall.SIGINT,syscall.SIGTERM) go func() { select { case sig := <-c: fmt.Printf("Got %s signal. Aborting...\n", sig) //task.Stop() close(task.closed) } }() //task.wg.Add(10) //for i := 0; i < 10; i++ { // go func(i int) { // defer task.wg.Done() // task.Run(i) // }(i) //} //task.wg.Wait() //fmt.Println("end") task.Run(1)
搞一个单独的线程用来接收需要监听的结束信号,这里只监听了SIGINT和SIGTERM;接收到结束信号后,发送一个关闭的信号;所有需要优雅关闭协程的goroutine都监听这个信号,一旦接收到这个信号,就退出。注意这里如果select case中有多个case条件满足的话,系统会随机选择一个select case执行,所以可能等多一会儿。