GO语言学习之goroutine

GO天生具有并发的特性。实现这一特性就采用了通道的技术。
先上代码:
package main

import (
“time”
)

func main() {
message := make(chan string)
//第一个版本
go func() {
message <- “ping”
}()
// // 等待通道发送数据,会阻塞
msg := <-message
fmt.Println(msg)
}
上面的代码是最简单的使用通道实现并发的用法。
首先是使用make创建了一个叫做string的通道,然后在go func里面使用“<-”把字符串放入该通道里面,最后在把通道的数据取出来。
如果在通道里面阻塞了会怎样呢?
func main() {
// message := make(chan string)
//在通道里面延迟
// go func() {
time.Sleep(1000000000000000000)
message <- “ping”
}()
// // 等待通道发送数据,会阻塞
msg := <-message
fmt.Println(msg)
}
在放入数据到通道里面的时候加入了延迟,模拟阻塞的情况。发现打印的时候明显过了一段时间才打印出来,从而可知道,从通道取数据的时候是会被阻塞的。如果通道没有数据则一直会阻塞到通道放入了数据。
现在模拟一个消息队列的实现

package main

import (
“fmt”
“strconv”
)

// 工作任务
type Job struct {
Id int
}

// 创建任务切片
func CreateJobs(len int) []Job {
jobs := make([]Job, len)
for index := 0; index < len; index++ {
job := Job{Id: index}
jobs[index] = job
}
return jobs
}

// 通过在同一缓冲区大小多试验几次,发现结果不同,经过分析是因为
// 两个协程是并行的所以才会产生不同的结果
func SendAndReceiveJob(capcty int) {
// 创建通道
out := make(chan Job)
// 创建任务列表
jobs := CreateJobs(10)
// 发送工作任务
go func() {
for _, job := range jobs {
out <- job
fmt.Println(“判断是否阻塞”)
}
close(out)
}()
//接受工作任务#
go func() {
for job := range out {
fmt.Println(“task id is ” + strconv.Itoa(job.Id))
}
}()
}
package main

import (
“time”
)

func main() {
SendAndReceiveJob(0)
// 如果不延迟则主goroutine退出,所以子goroutine也会退出
time.Sleep(1000000000)
}
通过以上代码的实践,得出了几个结论:
1 主goroutine与子goroutine是并行的,如果主goroutine已经退出了,那么子goroutine是不会执行了
2 发送数据的goroutine与接收数据的gotoutine是并行的,所以但把通道没有设置缓冲区的时候,多次实验打印的结果也是不一样的
3 当给通道设置了缓冲区的时候,当发送缓冲区的容量已满,则发送数据的goroutine会被阻塞,否则会继续执行。当接收数据的goroutine发现通道没有数据则接收数据的那方也会被阻塞,否则继续执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值