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),提供方法從信號量通道中讀取、寫入。

  • 一個互斥的例子

管道過濾

  • 從通道接收的數據併發送給輸出通道,可過濾符合條件的數據。

協程的恢復

  • 如下代碼停掉了服務器內部一個失敗的協程而不影響其餘協程的工做。

相關文章
相關標籤/搜索