慕雪6235644
2021-08-12 15:50
自己实现了一个,然后看了下老师的视频,发现实现方式完全不一样。
不知道老师有没时间看下我这个例子,指导下有啥优缺点。
另外看完了老师关于goroutine的系列课程,收获很多,感谢感谢
package main
import (
"fmt"
"time"
"sync"
)
//材料结构体
type data struct {
uid int //区分每个材料,便于打印展示
id int //区分每种材料,便于打印展示
time int //清洗耗时
}
var wg sync.WaitGroup
//每种材料个数
// var count int = rand.Intn(10) + 1
var count int = 5
var chanA = make(chan data, count*3)
var chanB = make(chan data, count)
var chanC = make(chan data, count)
//获取当前毫秒级时间
func now() int64 {
return (int64)(time.Now().UnixNano() / 1000 / 1000)
}
//清理材料
func A(id int) {
for {
select {
case d := <- chanA :
fmt.Printf("time:%d A车工人:%d,材料%d:%d 清洗中...\n", now(), id, d.id, d.uid)
time.Sleep((time.Duration)(d.time * 100) * time.Millisecond)
fmt.Printf("time:%d A车工人:%d,材料%d:%d 清洗完成\n", now(), id, d.id, d.uid)
//清理完成,放入加工管道
chanB <- d
default :
break
}
}
}
//加工材料
func B(id int) {
cnt := 0
for {
select {
case d := <- chanB :
fmt.Printf("time:%d B车工人:%d,材料%d:%d 加工中...\n", now(), id, d.id, d.uid)
time.Sleep(100 * time.Millisecond)
fmt.Printf("time:%d B车工人:%d,材料%d:%d 加工完成\n", now(), id, d.id, d.uid)
//加工完成,放入装载管道
chanC <- d
cnt += 1
default :
}
if cnt >= count {
break
}
}
}
//装载材料
func C(id int) {
for {
select {
case d := <- chanC :
fmt.Printf("time:%d C车工人:%d,材料%d:%d 装载中...\n", now(), id, d.id, d.uid)
time.Sleep(100 * time.Millisecond)
fmt.Printf("time:%d C车工人:%d,材料%d:%d 装载完成\n", now(), id, d.id, d.uid)
//清理完成,放入装载管道
wg.Done()
default :
}
}
}
func main() {
fmt.Println("demo start")
//声明3种材料需要的空间
var list []data = make([]data, count*3)
var d data
//填充3种材料的数据
for i := 0; i < count; i++ {
//填充第一种材料数据,清洗耗时6
d = data{uid : i, id : 1, time : 6}
list[i] = d
//填充第二种材料数据,清洗耗时3
d = data{uid : i, id : 2, time : 3}
list[i + count] = d
//填充第二种材料数据,清洗耗时3
d = data{uid : i, id : 3, time : 3}
list[i + count * 2] = d
}
//往清洗的管道按清洗时间长短填充
for i := 0; i < len(list); i++ {
chanA <- list[i]
}
//A车3个清洗工人
go A(1)
go A(2)
go A(3)
//B车3个加工工人
go B(1)
go B(2)
go B(3)
//C车3个装载工人
go C(1)
go C(2)
go C(3)
wg.Add(count*3)
wg.Wait()
fmt.Println("demo end")
}
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() }
Go并发之魂:Goroutine深入浅出【程序人生中的“米其林三星级”并发实战】
5503 学习 · 8 问题