目录
一、无缓冲channel单向传输
1、创建生产者与消费者模型
func send(ch chan<- int) {
for i := 0; i < 10; i++ {
ch <- i
}
}
func receive(ch <-chan int) {
for data := range ch {
fmt.Println(data)
}
}
注意当符号<-在chan右边代表往channel里发送数据,在左边代表从channel里取数据
2、增加main方法
func main() {
var wg sync.WaitGroup
ch := make(chan int)
wg.Add(1)
go send(ch)
go receive(ch, &wg)
wg.Wait()
}
增加wait方法是为了等待并发结束,能看到最终结果
在receive函数参数中添加wg是因为当消费者每接收一次done一次
3、修改生产者与消费者
生产者:
func send(ch chan<- int) {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
}
在其中增加了close方法,如果不增加则会发生死锁错误,意味着如果不进行关闭,消费者中wg.done就会一直阻塞,又导致wg.wait方法阻塞
消费者:
func receive(ch <-chan int, wg *sync.WaitGroup) {
defer wg.Done()
for data := range ch {
fmt.Println("接收数据:", data)
}
}
使用defer wg.done让消费者每消费一次执行计数器-1
最终运行结果:
接收数据: 0
接收数据: 1
接收数据: 2
接收数据: 3
接收数据: 4
接收数据: 5
接收数据: 6
接收数据: 7
接收数据: 8
接收数据: 9
二、有缓冲channel异步传输
1、修改消费者
给消费者增加处理时间
func receive(ch <-chan int, wg *sync.WaitGroup) {
defer wg.Done()
for data := range ch {
time.Sleep(1 * time.Second)
fmt.Println("接收数据:", data)
}
}
2、修改生产者
给生产者增加发送完成数据提醒
func send(ch chan<- int) {
for i := 0; i < 10; i++ {
ch <- i
}
fmt.Println("发送完成数据")
close(ch)
}
3、不修改main方法
最终输出结果:
接收数据: 0
接收数据: 1
接收数据: 2
接收数据: 3
接收数据: 4
接收数据: 5
接收数据: 6
接收数据: 7
接收数据: 8
发送完成数据
接收数据: 9
通过结果可以发现一直到沉默了9秒后才发送结束,效率不高
4、修改main方法
给main方法中channel增加缓冲
func main() {
var wg sync.WaitGroup
ch := make(chan int, 10)
wg.Add(1)
go send(ch)
go receive(ch, &wg)
wg.Wait()
}
最终结果:
发送完成数据
接收数据: 0
接收数据: 1
接收数据: 2
接收数据: 3
接收数据: 4
接收数据: 5
接收数据: 6
接收数据: 7
接收数据: 8
接收数据: 9
通过结果我们看到效率明显提高了,一执行就完成了数据的发送,达到了并行的效果,因为当给缓冲的时候数据可以直接写入channel而不用关心数据是否有人在读。简单来说就是有缓冲空间就可以直接写入,没有缓冲空间就必须一写一读的方式执行