GoLang之使goroutine停止的5种方法_什么是goroutine 如何停止-程序员宅基地

技术标签: golang  后端  GoLang  开发语言  

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 {
select {
}
}
对于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是可以向下传递的

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_52690231/article/details/123159765

智能推荐

通讯录程序_通讯录命令行界面数组保存-程序员宅基地

文章浏览阅读101次。#include<stdio.h>#include<stdlib.h>#include<string.h>#include<assert.h>#define MAX_PERSON 200#define MAX_NAME_SIZE 1024#define MAX_PHONE_SIZE 100//通过结构体表示一个现实中的事物的操作,成为"..._通讯录命令行界面数组保存

蒟蒻存图-程序员宅基地

文章浏览阅读137次。通往蒟蒻的最短路(存图篇)今天蒟蒻想学最短路但是本蒟蒻不会存图于是只好学习一下怎么存图1.不管不顾直接刚——临接矩阵优点:简单、易行、直观缺点:效率低、占用内存大可解少量图最大 mp[1000][1000];代码就不上了,重要的在后面。2.伸缩变换无穷尽——邻接表作为还没学链表的蒟蒻,只学会了vector版邻接表用结构体捆绑to和l,之后塞进起点对应的vector能满足大多..._蒟蒻存图

【笔记】来自MIT人工智能实验室:如何做研究_mit人工智能笔记-程序员宅基地

文章浏览阅读1.2k次。一 阅读阅读论文:找最领域内本质的论文。通过本领域的建议阅读列表、高年级前辈的建议获得。阅读期刊:最有价值的。AI领域:Artificial Intelligence(the Journal of Artificial Intelligence), Computational Intelligence, Machine Learning, IEEE PAMI(Pattern Analysi_mit人工智能笔记

使用html2Canvas实现截图功能_html2canvas iframe截图-程序员宅基地

文章浏览阅读7.5k次,点赞2次,收藏4次。通过JS就能截屏,这是Html2canvas为用户提供的一个便捷的神器,通过对DOM元素的信息提取渲染使用例子 :html2canvas($("#bg"), { onrendered: function (canvas) { var url = canvas.toDataURL(); //base64数据 var image = new Image(); image.src =_html2canvas iframe截图

利用广播与Service之间进行通信_广播和服务通信-程序员宅基地

文章浏览阅读724次。在程序中往往需要用到在前台控制后台的服务进行相关的操作。一方面可以直接绑定服务操作服务里面的内容。另一方面可以利用广播对Service里面的服务进行操作。当一个服务是通过startService启动。则只能选择通过广播进行与服务之间通信。例如如下程序是通过广播控制音乐的播放。具体流程如下:1、主页面启动控制音乐播放的操作。并且监听服务传递回来的状态对页面进行跟新操作 2、在服务中同时_广播和服务通信

后台返回的时间戳怎么转为前端的日期_后台返回时间戳前端转成时间-程序员宅基地

文章浏览阅读1.1k次。formTime(row, symbol) { let result = ""; if (row) { var data = new Date(); data.setTime(row); var year = data.getFullYear(); var month = data.getMonth() + 1; var day = data.getDate(); month = month < 10 ? "0" + month : month;_后台返回时间戳前端转成时间

随便推点

益农信息:农业物联网小气候自动监测站`····_益农农业监测系统-程序员宅基地

文章浏览阅读241次。小气候是指由于下垫面结构和性质不同,造成热量和水分收支差异,从而在小范围内形成一种与大气候不同特点的气候,统称小气候。农业小气候指的是以农作物为下垫面所形成的小气候,即指农业生活环境(如农田、果园、温室、畜舍等)和农业生产活动环境内(如晒场、喷药、农产品储运环境等)的气候。这些小气候与农业生产和农业生物有着密切的关系,主要表现为它们之间物质和能量的交换。农业小气候的范围,垂直方向大约为几米,一般不..._益农农业监测系统

(2)Mysql ----- The last packet successfully received from the server was *** millisecond ago.The-程序员宅基地

文章浏览阅读8.6w次,点赞6次,收藏38次。(1) http://programerni.diandian.com/post/2012-09-14/40038568893The last packet sent successfully to the server was 19365 milliseconds ago. The driver has not received any packets from the server._the last packet successfully received from the server was 5 milliseconds ago

ROM、RAM、FLASH、DDR、EMMC、SSD_fpga中ddr3和flash区别-程序员宅基地

文章浏览阅读8.4k次,点赞17次,收藏134次。目录ROM1.ROM2.PROM3.EPROM4.OTPROM5.EEPROM6.快闪存储器RAM1.静态随机存储器(SRAM)2.动态随机存储器(DRAM)SDRAMSDRAMDDR1DDR2DDR3flash一、存储数据的原理二、浮栅的重放电三、0 和 1四、连接和编址方式NAND flash和NO..._fpga中ddr3和flash区别

二 、TypeScript 变量和数据类型_ts为一个可能为null的值属性赋值-程序员宅基地

文章浏览阅读875次。一、什么是变量通俗的讲:变量,是用来存储数据的容器,并且是可以变化的。保温杯里泡枸杞,变量里面存数据。枸杞难挡岁月催,杯里再换点当归:枸杞 -> 当归。二、变量的使用2.1 基本使用变量的使用分为两步:1 声明变量并指定类型 2 给变量赋值。第一步:声明变量并指定类型let age :number;解释:let 是 TS 的关键字,用来声明变量。 age 是程序员自己定义的变量名称。 : number 用来指定变量 age 为数值类型。 注意:分._ts为一个可能为null的值属性赋值

Kali安装Googel拼音输入法_kali google拼音-程序员宅基地

文章浏览阅读1.2k次。打开kali终端输入:apt install fcitx安装输入法框架安装Googel拼音输入法命令:apt install fcitx-googlepinyin输入法安装完成后打开Fcitx配置;搜索框输入fcitx找到将安装的Googel拼音输入法排序为第一位在文本输入的情况下按shift键进行中英文切换;以上安装和配置部署完成了。输入reboot重启系统..._kali google拼音

mysql变量定义(declare,set,@)使用实例讲解_mysql declare-程序员宅基地

文章浏览阅读4.7k次。mysql变量的种类用户变量:以”@”开始,形式为”@变量名”。用户变量跟mysql客户端是绑定的,设置的变量,只对当前用户使用的客户端生效 全局变量:定义时,以如下两种形式出现,set GLOBAL 变量名 或者 set @@global.变量名,对所有客户端生效。只有具有super权限才可以设置全局变量 会话变量:只对连接的客户端有效。 局部变量:作用范围在begin到end语句..._mysql declare

推荐文章

热门文章

相关标签