在上一篇文章《Go语言开发基础系列(二十八)go语言并发编程之go关键词》我们介绍了在go语言中如何进行多线程编程,在最后其实留了一个疑问,就是我们主线程如果销毁了,不管子线程有没有执行完毕,都会直接被销毁。
在上一篇文章我们主要是使用time函数来主动让主线程阻塞的,但是在真实的环境中我们肯定是不能这么做,因为是无法评估子线程具体需要执行多久,这里的time阻塞需要定义多久,那怎么办呢?这里的话我们就可以使用chanel来实现。他的整个过程流程是:
主线程定义一个chanel 主线程创建一个多线程的子线程任务 子线程执行完毕之后通知主线程的chanel 主线程的chanel收到信号后继续往下执行
这个流程就能保证子线程的任务被正确的执行了,所以现在我们来演示一下:
1)定义一个chanel
done := make(chan bool) // 定义一个阻塞的chan
这里定义chan的时候,这是一个通道,他相当于是一个切片,done只是一个变量而已
2)创建一个子线程任务
func threadRun(threadNum int) { fmt.Println("线程执行了:", threadNum) }
这里创建的自选菜任务比较简单,暂不做过多介绍。
3)创建一个多线程去执行子任务
go func() { for i := 0; i < 10; i++ { threadRun(i) } }()
这里的话我们使用go关键词开启子线程去执行这个子线程任务,切记在这里的func里面我们最后的大括号里面需要有一个小括号,这是代表执行一个方法。
4)在线程执行完毕之后通知chan
done <- true
这里我们添加在go的子线程里面,主要是在子任务执行完毕之后通知chan,完整的代码示例如下:
go func() { for i := 0; i < 10; i++ { threadRun(i) } done <- true }()
5)在主线程中声明收到chan信号
<- done
这里的格式是固定的,固定为:
<- ${chain变量}
以上我们就完成了在go语言中主线程需要等待子线程完成之后才会继续执行后面的代码案例,这里我们来看看结果:
这里再编写一个比较简单的案例给大家看看效果,比上面的案例会更简单一些:
// demo1 project main.go package main import ( "bufio" "fmt" "os" ) /* * 创建一个异步执行的方法,从chanel里面获取数据 */ func printInput(ch chan string) { for a := range ch { if a == "EOF" { break } fmt.Println("input is: ", a) } } func main() { //创建chanel ch := make(chan string) //把channel放给异步任务进行并发执行 go printInput(ch) scanner := bufio.NewScanner(os.Stdin) //从控制台给chanel灌数据 for scanner.Scan() { a := scanner.Text() ch <- a if a == "EOF" { fmt.Println("end") break } } //结束的时候关掉chanel defer close(ch) }
可以看到这里我们不需要再手动的编写time函数来阻塞主线程,只有子线程执行完毕之后,才会执行主线程后面的代码。最后按照惯例,附上本案例的源码,登录后即可下载。
还没有评论,来说两句吧...