Go篇|高效的并发模式

这是我参与更文挑战的第9天,活动详情查看: 更文挑战

前几篇对并发编程基础元素goroutine、channel、sync包有所了解,接下来可利用这部分内容组成可使用的并发模式。

for select 循环模式

多路复用的并发模式,直到满足某条件退出for循环

// 模式1:
for{
	select{
		case <-done
		  return
    default:
      //执行具体的内容
	}
}

// 模式2:
for _,val := range []int{
  select {
    case <-done:
     return
    case resCh <-val:
    ...
    if .. {
      done <- ??
    }
  }
}
复制代码
  • 模式1:一直执行default语句中的任务,直到执行done后被关闭停止
  • 模式2:有限循环,resCh接收循环的值,可通过满足某条件将值传递给done,这样就可以退出当前循环,或者其他方式

select timeout模式

请求数据时,因网络不同响应时间也不同,为避免出现一直等待那些超时请求,我们需要设置一个超时时间,可使用select timeout模式

select {
	case v := <-result
	  ...
	case <-time.After(5 * time.Second)
	   fmt.Println("网络访问超时了")
}
复制代码

主要通过time.After函数设置一个超时时间,防止因异常导致select语句无限等待。如果存在Context,可优先使用context.WithTimeout函数

Pipeline模式

管道模式(流水线模式),类似一个流水线生产,经过多个工序作业完成最后的成品。

  • 流水线由多道工序构成,每道工序通过channel将数据传递到下一个工序,即每道工序的入参都是上游工序的返回值,产生的值继续传递给下游工序
  • 每道工序对应一个函数,函数中有协程和channal,函数处理数据,并把它放在channel中,最后返回channel给下一道工序使用
  • 组织者将所有工序串联起来,形成完整的流水线
// 
func main(){
  first := build1()
  second := build2(first)
  third := build3(second)
}
//工序1
func build1(in <-chan string) <-chan string{
  out := make(chan string)
  
  go func(){
    defer close(out)
    for c:= range in{
       out <- "组装(“+c+”)"
    }
  }()
  
  return out
}
// 工序2
func build2(in <-chan string) out chan string{
  ...
}
// 工序3
func build3(in <-chan string) out chan string{
  ...
}
复制代码

扇出和扇入模式

扇出:多个函数可以从同一个通道读取数据,直到通道关闭

扇入:一个函数可以从多个通道读取数据,直到通道关闭

func main(){
  in := gen(1)
  
  c1 := sq(in)
  c2 := sq(in)
  
  for n := range merge(c1,c2){
    fmt.Println(n) 
  }
}

func sq(in <-chan string) chan string{
  out := make(chan string)
  go func(){
    ...
  }
  return out 
}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享