简介 目录 评价 推荐
  • 慕粉1453012542 2022-02-09
    上边的代码main函数执行会提前退出,不执行gofunc

    要延迟去处理就可以了

    1回答·402浏览
  • 慕雪6235644 2021-08-12
    初学go,求指教
    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()
    }


    1回答·383浏览
  • 慕粉第一号 2021-08-07
    这样为什么报错

    这是因为ch<- 1 这个操作,是阻塞操作,就是说 遇到了 a<-1 代码就不走了,什么时候代码往下走?必须等到ch里面的消息被读出去才会继续走

    可以简单改为:

    ch := make(chan int)
    
    // fmt.Println(ch)
    go func() {
       ch <- 1
    }()
    
    // 输出channel
    
    go func() {
    
       fmt.Println(<-ch)
    
    }()
    time.Sleep(time.Second*2)


    1回答·437浏览
  • 慕粉第一号 2021-08-07
    无缓存channel为什么在如下场景会失败?
    2回答·442浏览
  • 大菠萝965661 2021-07-31
    为什么B函数里面要写两个for循环

    你用你的想法用代码来试一下比对一下吧

    1回答·390浏览
  • bongIO好 2020-11-07
    老师您好,请问一下为什么不是流水线形式的?就是A处理完一个element直接通过channel传给B,然后A继续处理其他的element,最后在C处进行收集。这样子不是更能体现并发的好处吗?

    小伙伴客气啦!其实流水线形式也是可以的,这里只是提供了一种可能的案例
    在提问中提到的流水线形式,可能会存在一种,由于频繁使用channel传输数据的形式,而造成一定程度的额外耗时
    所以我们在设计并发代码的时候,在某些为了通过并发加速计算的场景下,通常会尽可能地避免使用到channel

    1回答·430浏览
  • 宝慕林0163075 2020-07-04
    一月又一月

    ?抱歉,没理解你的意思,能否给点提示?

    1回答·488浏览
  • 羊毛梦 2020-06-03
    视频缺失

    已经添加上了吧

    1回答·376浏览
数据加载中...
开始学习 免费