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

目录
  • 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并发编程中很常用,这对于从单一通道上获取数据去执行某些任务是十分方便的

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

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

当我们就需要向quit通道中发送100次数据,如果再用以上的代码就很麻烦,有一个很简单的方法,关闭channel,这样所有监听quit channel的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()
}

2.5使用context包

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

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

总结

到此这篇关于GoLang使goroutine停止的五种方法的文章就介绍到这了,更多相关GoLang goroutine停止内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang goroutine顺序输出方式

    range字符串,使用goroutine打印 因为goroutine随机执行 for _, v := range str { go func() { fmt.Println(string(v)) }() } 输出: 5 5 5 5 5 可以使用chan顺序输出 for _, c := range str{ ch := make(chan rune) go func(ch <-chan rune) { key := <-ch fmt.Println(string(key)) }(ch) ch &

  • Golang 语言控制并发 Goroutine的方法

    goroutine 是 Go语言中的轻量级线程实现,由 Go 运行时(runtime)管理.Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU. 01介绍 Golang 语言的优势之一是天生支持并发,我们在 Golang 语言开发中,通常使用的并发控制方式主要有 Channel,WaitGroup 和 Context,本文我们主要介绍一下 Golang 语言中并发控制的这三种方式怎么使用?关于它们各自的详细介绍在之前的文章已经介绍过,感兴趣的读者朋友们可以按需翻阅. 02

  • Golang Goroutine的使用

    什么是 Goroutine goroutine 是 Go 并行设计的核心.goroutine 说到底其实就是协程,它比线程更小,十几个 goroutine 可能体现在底层就是五六个线程,Go 语言内部帮你实现了这些 goroutine 之间的内存共享. 执行 goroutine 只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩.也正因为如此,可同时运行成千上万个并发任务.goroutine 比 thread 更易用.更高效.更轻便. 一般情况下,一个普通计算机跑几十个线程就有点负载

  • 解决Golang中goroutine执行速度的问题

    突然想到了之前一直没留意的for循环中开goroutine的执行顺序问题,就找了段代码试了试,试了几次后发现几个有意思的地方,我暂时没有精力往更深处挖掘,希望有golang大神能简单说一说这几个地方是怎么回事. 代码: package main import "fmt" func Count(ch chan int) { fmt.Println("Count doing") ch <- 1 fmt.Println("Counting") }

  • Golang 探索对Goroutine的控制方法(详解)

    前言 在golang中,只需要在函数调用前加上关键字go即可创建一个并发任务单元,而这个新建的任务会被放入队列中,等待调度器安排.相比系统的MB级别线程栈,goroutine的自定义栈只有2KB,这使得我们能够轻易创建上万个并发任务,如此对性能提升不少.但随之而来的有以下几个问题: 如何等待所有goroutine的退出 如何限制创建goroutine的数量(信号量实现) 怎么让goroutine主动退出 探索--如何从外部杀死goroutine 本文记录了笔者就以上几个问题进行探究的过程,文中给

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

    目录 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

  • Android实现定时器的五种方法实例详解

    一.Timer Timer是Android直接启动定时器的类,TimerTask是一个子线程,方便处理一些比较复杂耗时的功能逻辑,经常与handler结合使用. 跟handler自身实现的定时器相比,Timer可以做一些复杂的处理,例如,需要对有大量对象的list进行排序,在TimerTask中执行不会阻塞子线程,常常与handler结合使用,在处理完复杂耗时的操作后,通过handler来更新UI界面. timer.schedule(task, delay,period); task: Time

  • C++ 字符串的反转五种方法实例

    复制代码 代码如下: //通过不同的方法,实现对所输入字符串的反转,可以很好地复习巩固 C++ 基础知识/*分析过程: 假设要使传递的字符串为常量const字符串,这样操作更加灵活,可直接传递字符串字面值进行反转,常见的解决方法就是,定义一个新的与传递过来字符串长度 相等的字符数组,然后进行字符串拷贝,把str字符按从左到右放置到字符数组中,然后采用循环来对字符数组中字符反转*//*第一种,采用以上思路解法,传递为const类型C风格字符指针,返回为char*类型*///直接使用字符数组赋值ch

  • nullJavascript中创建对象的五种方法实例

    复制代码 代码如下: <script type="text/javascript"> // 方法一var p0 = new Object();p0.name = "xy";p0.age = 20;p0.sayName = function() { alert(this.name); }p0.showAgeAfterSomeYears = function(year) { return this.age + year };p0.sayName();aler

  • JavaScript数组去重的五种方法

    javascript数组去重是一个比较常见的需求,解决方法也有很多种,网上都可以找到答案的,下面小编给大家整理了一份关于同类型的数组去重的方法,先给大家介绍下简单实现思路. 思路: 遍历数组,一一比较,比较到相同的就删除后面的 遍历数组,一一比较,比较到相同的,跳过前面重复的,不相同的放入新数组 任取一个数组元素放入新数组,遍历剩下的数组元素任取一个,与新数组的元素一一比较,如果有不同的,放入新数组. 遍历数组,取一个元素,作为对象的属性,判断属性是否存在 1. 删除后面重复的: functio

  • 详解Go语言中用 os/exec 执行命令的五种方法

    完整系列教程详见:http://golang.iswbm.com 在 Golang 中用于执行命令的库是 os/exec,exec.Command 函数返回一个 Cmd 对象,根据不同的需求,可以将命令的执行分为三种情况 只执行命令,不获取结果 执行命令,并获取结果(不区分 stdout 和 stderr) 执行命令,并获取结果(区分 stdout 和 stderr) 第一种:只执行命令,不获取结果 直接调用 Cmd 对象的 Run 函数,返回的只有成功和失败,获取不到任何输出的结果. pack

  • maven工程中jar包瘦身的五种方法

    java项目中常用maven工具来进行工程管理,但经常遇到的一个问题是生成的jar包越来越大,编译一次工程越来越慢.怎么有效地去除冗余依赖,给jar包进行瘦身,是一项必备技能.下面介绍在maven工程中jar包瘦身五大法: 一.将环境中已包含的依赖包的scope设置为provided pom中依赖的部分包可能在你程序运行环境中已经包含,此时应该将依赖包的scope设置为provided.如protobuf包如在环境中已包含,则应设置为: <dependency> <groupId>

  • 浅谈基于SQL Server分页存储过程五种方法及性能比较

    在SQL Server数据库操作中,我们常常会用到存储过程对实现对查询的数据的分页处理,以方便浏览者的浏览. 创建数据库data_Test : create database data_Test GO use data_Test GO create table tb_TestTable --创建表 ( id int identity(1,1) primary key, userName nvarchar(20) not null, userPWD nvarchar(20) not null, u

  • js实现页面跳转的五种方法推荐

    js实现页面跳转的五种方法推荐 第一种: 复制代码 代码如下: <script language="javascript" type="text/javascript"> window.location.href="xx.jsp?backurl="+window.location.href; </script> 第二种: 复制代码 代码如下: <script language="javascript&quo

  • php获取超链接文本内容的正则表达式(五种方法)

    废话不多说了,直接跟大家分享五种方法,通过代码讲解php获取超链接文本内容的正则表达式. //方法一 preg_match_all("/<(a|a)[s]{0,1}[w=":()]*>[ ]*(check user)[ ]*</(a|a)>/i",$string,$matches); //方法二 preg_match_all("/<a[dd]*>check user</a>/i",$string,$match

随机推荐