说说channel哪些事-下篇

在channel-上篇中,小编主要从channel是什么,为什么需要channel,channel基本的使用方法以及channel实现原理这个四个方面介绍了channel.本篇,小编将从实际的应用场景出发,介绍如何运用chnanel解决这些问题。
channel解决的主要是并发问题,学习下面的场景,总结提炼用法,可以帮助我们更好的编写并发程序。

for+select多路复用模式

for+select多路复用模式非常常见,在实际的工作中也使用的非常频繁,其基本代码模式如下:

for {
		select {
		case 操作 channel one:
			do something
		case 操作 channel two:
			do something
		case ...:
			do something
		}
	}

select后面跟多个case,每个case是一个channel操作,操作有两种,向channel里面发送数据,或者是从channel里面取数据,哪个case满足,就执行对应case后面的操作。如果同时有多个case满足,会随机选一个执行。下面举一个实例.exitCh和tasksCh是两个channel, 通过select同时监听两个case是否满足,exitCh是一个退出chan,如果收到通知,直接退出循环,tasksCh是任务chan,收到数据就进行处理。下面的select中也可以添加一个default分支,如果其他case不满足,会走到default分支。

exitCh = make(chan struct{})
tasksCh = make(chan interface{}, 8)

for {
  select {
  case <-exitCh:
        return
  case data := <-tasksCh:
        process(data)
      }
}

select+timeout模式

select+timeout模式也很常见,比如一个服务需要访问数据库或者向其他模块请求数据,因为处理的时间不能确定,不可能一直等待它们处理完成,等待太长用户体验不好,这时可以设置一个超时时间,如果超过这个时间数据库还没处理完,或者没有请求到数据,提前返回给用户提示。这种场景就可以使用select+timeout模式。
下面结合一个例子说明,select同时监听了taskCh和time.After,这个例子会输出处理超时了,也就是走到到time.After逻辑里面。因为taskCh通道中有数据会在5秒后,这里模拟一个耗时比较长的任务,time.After里面超时是1秒中,所以第二个case先满足。
说明下,time.After返回的也是一个channel,类型为<-chan Time,可以在time/sleep.go中查看。 在1秒时间到后,会往此channel里面发送一个数据。

func main() {
	taskCh := make(chan int)
	go func() {
		//模拟长耗时任务
		time.Sleep(5 * time.Second)
		taskCh <- 1
	}()

	select {
	case data := <-taskCh:
		fmt.Println(data)
	case <-time.After(1 * time.Second):
		fmt.Println("处理超时了")
	}
	// 输出:处理超时了
}

pipeline流水线模式

pipeline模式也被称为流水线模式,模拟的就是现实生活中的流水线生产。拿一部电动汽车生产来说,有做底盘的,有做轮胎的,有做发动机的,有做车壳的,最后将经过组装,就变成了一部汽车。
每第一道工序的输出是下一道工序的输出,下一道工序制作依赖上一道工序,整个加工的产品在工序之间传递。整个流程可以抽象成生产者消费者模型,如下图,对于工序2来来说,工序1是生产者,工序3是消费者,对于工序3来说,工序2是生产者。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
理解了流水线模式,现在来实战下。
说说channel哪些事-下篇_第1张图片

有3个编号为1,2,3的goroutine,每隔1秒有1个goroutine打印自己的编号。编写一个程序,让输出的编号信息按1,2,3,1,2,3,1,2,3

你可能感兴趣的:(golang,编程语言,golang,并发编程,高并发编程)