目录
  • 1.goroutine停止介绍
  • 2.goroutine停止的5种方法
    • 2.1使用for-range
    • 2.2使用for-select(向退出通道发出退出信号)
    • 2.3使用for-select(关闭退出通道)
    • 2.4使用for-select(关闭多个channel)
    • 2.5使用context包
  • 总结

    GoLang之使goroutine停止的5种方法

    1.goroutine停止介绍

    goroutine是Go语言实现并发编程的利器,简单的一个指令go function就能启动一个goroutine;

    但是,Go语言并没有提供终止goroutine的接口,也就是说,我们不能从外部去停止一个goroutine,只能由goroutine内部退出(main函数终止除外);

    我们有很多情况下需要主动关闭goroutine,如需要实现一个系统自动熔断的功能就需要主动关闭goroutine

    2.goroutine停止的5种方法

    2.1使用for-range

    for-range从channel上接收值,直到channel关闭,该结构在Go并发编程中很常用,这对于从单一通道上获取数据去执行某些任务是十分方便的

    GoLang使goroutine停止的五种方法实例

    GoLang使goroutine停止的五种方法实例

    2.2使用for-select(向退出通道发出退出信号)

    当channel比较多时,for-range结构借不是很方便了;

    Go语言提供了另外一种和channel相关的语法: select;

    select能够让goroutine在多个通信操作上等待(可以理解为监听多个channel);

    由于这个特性,for-select结构在Go并发编程中使用的频率很高;

    我在使用Go的开发中,这是我用的最多的一种组合形式:

    for {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->
    select {<!--{C}%3C!%2D%2D%20%2D%2D%3E-->
    }
    }
    

    对于for-select结构,一般我会定义一个特定的退出通道,用于接收退出的信号,如quit

    GoLang使goroutine停止的五种方法实例

    2.3使用for-select(关闭退出通道)

    当我们就需要向quit通道中发送100次数据,如果再用以上的代码就很麻烦,有一个很简单的方法,关闭channel,这样所有监听quit channel的goroutine就都会收到关闭信号,上面的代码只要做一个很小的替换就能工作

    GoLang使goroutine停止的五种方法实例

    2.4使用for-select(关闭多个channel)

    如果select上监听了多个通道,需要所有的通道都关闭后才能结束goroutine,这里就利用select的一个特性,select不会在nil的通道上进行等待,因此将channel赋值为nil即可,此外,还需要利用channel的ok值

    var wg sync.WaitGroup
    func worker(in1, in2 <-chan int) {
    	defer wg.Done()
    	for {
    		select {
    		case v, ok := <-in1:
    			if !ok {
    				fmt.Println("收到退出信号")
    				in1 = nil
    			}
    			// do something
    			fmt.Println(v)
    		case v, ok := <-in2:
    			if !ok {
    				fmt.Println("收到退出信号")
    				in2 = nil
    			}
    			// do something
    			fmt.Println(v)
    		}
    		// select已经结束,我们需要判断两个通道的状态
    		// 都为nil则结束当前goroutine
    		if in1 == nil && in2 == nil {
    			return
    		}
    	}
    }
    func main() {
    	in1 := make(chan int) // 退出通道,接收
    	in2 := make(chan int)
    	wg.Add(2)
    	go worker(in1, in2)
    	go worker(in2, in2)
    	for i := 0; i < 3; i++ {
    		in1 <- i
    		time.Sleep(1 * time.Second)
    		in2 <- i
    	}
    	close(in1)
    	close(in2)
    	wg.Wait()
    }
    

    GoLang使goroutine停止的五种方法实例

    2.5使用context包

    context包是官方提供的一个用于控制多个goroutine写作的包;

    使用context的cancel信号,可以终止goroutine的运行,context是可以向下传递的

    总结

    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。