fork and join
package main import ( "fmt" "sync" "time" ) var global = sync.WaitGroup{} // A车传送给B车的通道 var ch1 = make(chan *material, 3) // B车传送给C车的通道 var ch2 = make(chan *material, 3) // 食材 type material struct { // 食材名称 name string // 食材数量 count byte // A车处理所需花费时间,单位秒 elapsedTimeA uint // B车处理所需花费时间,单位秒 elapsedTimeB uint // C车处理所需花费时间,单位秒 elapsedTimeC uint } func main() { global.Add(3) // 所有需要处理的食材 materials := []*material{ {"白菜", 12, 2, 1, 1}, {"青菜", 12, 1, 1, 1}, {"胡萝卜", 12, 1, 1, 1}, } start := time.Now() go A(materials) go B() go C() global.Wait() cost := time.Since(start) fmt.Printf("总耗时:%s\n", cost) } func A(materials []*material) { fmt.Printf("A车出发\n") // 循环处理每种食材 for _, ele := range materials { var worker = sync.WaitGroup{} worker.Add(3) // 3名工人分别处理每种食材的1/3 for i := 0; i < 3; i++ { go func(index int, ele2 *material) { fmt.Printf("A车工人[%d]正在清洗食材[%s],数量[%d],预计耗时[%d]秒\n", index, ele2.name, ele2.count/3, ele2.elapsedTimeA) // 睡眠模拟处理食材耗时 time.Sleep(time.Second * time.Duration(ele2.elapsedTimeA)) worker.Done() }(i, ele) } // 等待所有工人都处理完毕后,把处理后的食材传送给B车 worker.Wait() fmt.Printf("A车食材[%s]正在运往B车\n", ele.name) ch1 <- ele } fmt.Printf("A车任务结束\n") global.Done() } func B() { fmt.Printf("B车出发\n") // 循环处理3种食材 for i := 0; i < 3; i++ { // 从通道取不到数据时会阻塞,只有通道关闭时ok才等于false,所以下面的if判断可以忽略 ele, ok := <-ch1 if !ok { break } fmt.Printf("B车接收到A车食材[%s]\n", ele.name) var worker = sync.WaitGroup{} worker.Add(3) for j := 0; j < 3; j++ { go func(index int, ele2 *material) { fmt.Printf("B车工人[%d]正在加工食材[%s],数量[%d],预计耗时[%d]秒\n", index, ele2.name, ele2.count/3, ele2.elapsedTimeB) // 睡眠模拟处理食材耗时 time.Sleep(time.Second * time.Duration(ele2.elapsedTimeB)) worker.Done() }(j, ele) } // 等待所有工人都处理完毕后,把处理后的食材传送给C车 worker.Wait() fmt.Printf("B车食材[%s]正在运往C车\n", ele.name) ch2 <- ele } fmt.Printf("B车任务结束\n") global.Done() } func C() { fmt.Printf("C车出发\n") for i := 0; i < 3; i++ { // 从通道取不到数据时会阻塞,只有通道关闭时ok才等于false,所以下面的if判断可以忽略 ele, ok := <-ch2 if !ok { break } fmt.Printf("C车接收到B车食材[%s]\n", ele.name) var worker = sync.WaitGroup{} worker.Add(3) for j := 0; j < 3; j++ { go func(index int, ele2 *material) { fmt.Printf("C车工人[%d]正在装载食材[%s],数量[%d],预计耗时[%d]秒\n", index, ele2.name, ele2.count/3, ele2.elapsedTimeC) // 睡眠模拟处理食材耗时 time.Sleep(time.Second * time.Duration(ele2.elapsedTimeC)) worker.Done() }(j, ele) } worker.Wait() } fmt.Printf("C车任务结束\n") global.Done() }
总结总结总结
面试题之白板写代码
面试题之解题逻梳理
面试题之梳理
面试题之考点
实操案例:生产者和消费者
如何利用 channel 阻塞
企业级解决办法
Channel 阻塞的重后果
Channe 阻塞条件
Channel 阻塞
什么是 Channel 阻塞
本章概览1
Channe 资源爭抢
资源争抢应用场景
案例规约1
fmt.Println(ch)
怎么使用 hannel
Channel 的妙用
本章概览1
Goroutine Done
协程生命周期
多协程边界问题
多协程等待的实现方式
烹方式设计-复合型