package main import ( "fmt" "time" ) var amount = 5 // 一共需要生产多少个产品 var produceChan = make(chan int, amount) // 生产管道 var sellOutChan = make(chan int, 1) // 标记是否售罄管道 func produce() { // 开始生产产品,共需要生产amount个 for i := 1; i <= amount; i++ { produceChan <- i // 向生产管道发送数据 fmt.Printf("第%+v个产品已生产 \n", i) time.Sleep(time.Millisecond * 500) // 生产完一个产品后休眠一段时间 } // 已生产完amount个产品,可以关闭管道 close(produceChan) fmt.Printf("生产:生产已完成 \n") } func sell() { // 开始销售产品,这里无需知道amount的值,生产多少就卖多少,直到停止生产 for { i, success := <-produceChan // 从生产管道接收数据 if !success { break } fmt.Printf("第%+v个产品已卖出 \n", i) } // 标记产品已售罄,并关闭该管道 sellOutChan <- 1 close(sellOutChan) fmt.Printf("销售:产品已售罄 \n") } func main() { // 开启两个协程,一个生产一个销售,生产和销售互不干扰,但又有所关联(必须生产了才能销售) go produce() // 生产协程 go sell() // 销售协程 // 开启一个死循环检查产品是否已售罄 for { _, success := <-sellOutChan if !success { fmt.Printf("即将break死循环,完成main()函数 \n") break } } //========== 输出过程·开始 ==========// // 第1个产品已生产 // 第1个产品已卖出 // 第2个产品已生产 // 第2个产品已卖出 // 第3个产品已生产 // 第3个产品已卖出 // 第4个产品已生产 // 第4个产品已卖出 // 第5个产品已生产 // 第5个产品已卖出 // 生产:生产已完成 // 销售:产品已售罄 // 即将break死循环,完成main()函数 //========== 输出过程·结束 ==========// } //========== 总结 ==========// // 1、管道对于协程是线程安全的,不会发生资源竞争的问题,故生产完一个产品虽然会休眠一段时间,但并不受影响销售,因为是生产完 // 一个产品之后销售才能拿到产品去卖,并且是先生产的先销售。 // 2、管道应该由数据发送方来关闭,即谁向管道发送数据,就由谁来关闭这个管道。
Copyright © 2024 码农人生. All Rights Reserved