Golang的通道技巧

计时器及系统负荷均衡

  • time包中的 time.Ticker结构体,该对象以指定的时间间隔重复向结构体中的通道C发送时间值,通道C对用户只读,该对象可经过工厂函数 time.NewTicker(dur int64) 建立,dur是指定的时间间隔,单位为纳秒(ns)。在使协程周期性执行任务(打印状态日志,输出等)时使用。调用Stop() 使计时器中止,与 select结合以下:
  • time.Tick()函数声明为 Tick(d Duration) <-chan Time,该函数返回的通道不须要关闭,它以 d为周期给返回的通道发送时间,d是纳秒数。能够经过此函数限制处理频率,若是应对的请求不平稳,能够增长一个带缓冲的可读写通道,从chRate中读取处理时钟,在请求暴增时能够快速处理与缓冲数相等的请求,以后处理速度会降低到和chRate 同样的速率。

  • 定时器(Timer)定时器和计时器(Ticker)结构体相似(构造函数为 NewTimer(d Duration)),但它只发送一次时间,在 Dration d以后。算法

  • time.After(d) 函数声明为 func After(d Duration) <-chan Time,在 Duration d 以后,当前时间被发到返回的通道;所以它和NewTimer(d).C等价;它相似 Tick(),但 After() 只发送一次时间。可使用此函数应对简单的超时模式,如下为三种形式。数据库

    • 要执行某个任务(如从通道 ch 中读取数据),但最多等待1秒。先建立一个信号通道,以后启动一个lambda 协程,协程在给通道发送数据前休眠:

    • time.After()函数替换 timeout-channel。能够在 select 中使用来让发送信号超时或中止协程的执行。如下代码,在 timeoutNs 纳秒后执行 selecttimeout分支后,包含client.Calllambda协程也随之结束,不会给通道ch 返回值。缓冲大小设置为 1 是必要的,能够避免协程死锁以及确保超时的通道能够被垃圾回收。须要注意若是 select 中的某些非定时器选项的通道读写密集,则可能没法结束这些进程。这种状况若是将select 放到一个for 循环中,也没法精确地在定时器通道写入时就结束,由于select对能够执行的多个 case 采起伪随机算法选择,可能结束进程的时间要比定时器发出信号略晚一些。

    • 假设程序从多个复制的数据库同时读取,只须要接收首先到达的答案,Query 函数获取数据库的链接切片,并行请求每个数据库并返回收到的第一个响应。结果通道 ch 必须是带缓冲的,以保证第一个发送进来的数据有地方能够存放,确保放入的首个数据总会成功:

缓冲通道实现信号量模式

使用缓冲通道模拟信号量,需知足

  • 带缓冲通道的容量和要同步的资源容量相同服务器

  • 通道的长度(当前存放的元素个数)与当前资源被使用的数量相同并发

  • 容量减去通道的长度就是未处理的资源个数(标准信号量的整数值)函数

  • 建立一个可缓冲通道表示单一信号量。日志

  • 将可用资源的数量N来初始化信号量 semaphore:sem = make(semaphore, N),提供方法从信号量通道中读取、写入。

  • 一个互斥的例子

管道过滤

  • 从通道接收的数据并发送给输出通道,可过滤符合条件的数据。

协程的恢复

  • 如下代码停掉了服务器内部一个失败的协程而不影响其余协程的工做。

相关文章
相关标签/搜索