Go 語(yǔ)言編程實(shí)例(三)

斷續(xù)器

計(jì)時(shí)器 是當(dāng)想在未來(lái)做一些事情 - tickers 是用于定期做一些事情跛蛋。這里是一個(gè)例行程序登馒,周期性執(zhí)行直到停止式曲。

代碼使用與計(jì)時(shí)器的機(jī)制類似:發(fā)送值到通道义矛。這里我們將使用通道上的一個(gè)范圍內(nèi)來(lái)迭代发笔,每隔500ms發(fā)送一次。

代碼可以像定時(shí)器一樣停止凉翻,當(dāng)代碼停止后了讨,它不會(huì)再其通道上接收值。

package main

import (
    "time"
    "fmt"
)

func main(){
    ticker := time.NewTicker(time.Millisecond * 500)

    go func() {
        for t := range ticker.C{
            fmt.Println("Tick at ",t)
        }
    }()

    time.Sleep(time.Millisecond * 1600 )
    ticker.Stop()
    fmt.Println("Ticker stopped")
}

Go 工作池

在這個(gè)例子中制轰,我們將實(shí)現(xiàn)如何使用 goroutinechannel 實(shí)現(xiàn)一個(gè)工作池量蕊。

這里是工作程序(worker),我們將運(yùn)行幾個(gè)并發(fā)實(shí)例艇挨。這些工作程序(worker)將在工作 chan 上接收工作残炮,并將發(fā)送相應(yīng)的結(jié)果。這里使用 延時(shí)1s的方式模擬工作的過(guò)程缩滨。

為了使用工作程序(worker)池势就,需要向他們發(fā)送任務(wù)并收集相關(guān)結(jié)果。這里實(shí)現(xiàn)的時(shí)候使用了兩個(gè)通道脉漏。這啟動(dòng)了 3 個(gè)worker苞冯,最初被阻止,因?yàn)闆](méi)有任務(wù)侧巨。

然后手機(jī)作業(yè)的所有結(jié)果舅锄。

package main

import (
    "fmt"
    "time"
)

//worker本體函數(shù)
func worker(id int,job <-chan int, result chan<- int){
    for j:=range job{
        fmt.Println("worker",id,"started job",j)
        time.Sleep(time.Second)
        fmt.Println("worker",id,"finished job",j)
        result<- j*2
    }
}

func main(){
    jobs:= make(chan int,100)
    results := make(chan int,100)

    //創(chuàng)建3個(gè)worker
    for w:=1 ; w<= 3;w++{
        go worker(w,jobs,results)
    }

    //分配5個(gè)任務(wù)
    for j:=1 ;j<= 5 ; j++{
        jobs <- j
    }

    close(jobs)

    //等待所有工作完成
    for a :=1 ; a<=5 ; a++{
        <- results
    }
}

Go 速率限制

速率限制是控制資源利用和維持服務(wù)質(zhì)量的重要機(jī)制。通過(guò) goroutines司忱,channel皇忿,ticker 都可以優(yōu)雅的支持速率限制。

首先我們來(lái)看一下基本速率限制坦仍。假設(shè)想限制對(duì)傳入請(qǐng)求的處理鳍烁。我們需要在同一個(gè)通道上處理。

這個(gè)限制器通道將 2000ms 接收一個(gè)值繁扎。這是速率限制方案中的調(diào)節(jié)器幔荒。

通過(guò)在服務(wù)每個(gè)請(qǐng)求之前阻塞來(lái)自限制器信道的接收糊闽,我們限制自己每200ms接收一個(gè)請(qǐng)求。

我們可能希望在速率限制方案中允許端脈沖串請(qǐng)求爹梁,同時(shí)保持總體速率限制右犹。可以通過(guò)緩沖的限制器通道來(lái)實(shí)現(xiàn)姚垃。這個(gè) burstyLimiter通道將允許最多 3 個(gè)事件的突發(fā)傀履。

填充通道以表示允許突發(fā)。

每2000ms莉炉,將嘗試向 burstyLimiter添加一個(gè)新值,最大限制為 3 〔耆現(xiàn)在模擬 5個(gè)更多的傳入請(qǐng)求絮宁。這些傳入請(qǐng)求的前三個(gè)未超過(guò)burstyLimiter 值。

package main

import (
    "time"
    "fmt"
)

func main(){
    requests := make(chan int , 5)
    for i:= 1 ; i<= 5 ; i++{
        requests <- i
    }
    close(requests)

    limiter := time.Tick(time.Millisecond * 2000)

    for req := range requests{
        <- limiter
        fmt.Println("request",req,time.Now())
    }

    burstyLimiter := make(chan time.Time , 3)

    for i:= 0 ; i<3;i++{
        burstyLimiter <- time.Now()
    }

    go func() {
        for t:= range time.Tick(time.Millisecond * 2000){
            burstyLimiter <- t
        }
    }()

    burstyRequests := make(chan int , 5)
    for i:=1 ; i<= 5 ; i++{
        burstyRequests <- i
    }
    close(burstyRequests)

    for req := range burstyRequests{
        <- burstyLimiter
        fmt.Println("request",req,time.Now())
    }
}

Go原子計(jì)數(shù)器

go語(yǔ)言中管理狀態(tài)的主要機(jī)制是通過(guò)通道進(jìn)行通信服协。在過(guò)去的文章中绍昂,我們已經(jīng)看到了這一點(diǎn),例如工作池偿荷。還有一些其他選項(xiàng)用于管理狀態(tài)窘游。這里我們將使用 sync/atomic 包來(lái)實(shí)現(xiàn)由多個(gè) goroutine 訪問(wèn)的原子計(jì)數(shù)器。

使用一個(gè)無(wú)符號(hào)整數(shù)表示計(jì)數(shù)器(正數(shù))

為了模擬并發(fā)更新跳纳,將啟動(dòng) 50個(gè) goroutine 忍饰, 每個(gè)增量計(jì)數(shù)器大學(xué)是 1ms。

為了原子地遞增計(jì)數(shù)器寺庄,這里使用 AddUint64() 函數(shù)艾蓝,在 ops 計(jì)數(shù)器的內(nèi)存地址上使用 & 語(yǔ)法。

為了安全地使用計(jì)數(shù)器斗塘,同時(shí)它任然被其他 goroutine 更新赢织。通過(guò) LoadUint64提取一個(gè)當(dāng)前值的副本到 opsFinal。如上所述馍盟,需要獲取值的內(nèi)存地址 &ops 給這個(gè)函數(shù)于置。

運(yùn)行程序顯示執(zhí)行了大約 40000次操作。根據(jù)自己機(jī)器性能可以嘗試其他更nice的操作贞岭。

package main

import (
    "sync/atomic"
    "time"
    "fmt"
)

func main(){
    var ops uint64 = 0


    for i:= 0 ; i< 50 ; i++{
        go func() {
            for{
                atomic.AddUint64(&ops,1)
                time.Sleep(time.Millisecond * 1 )
            }
        }()
    }

    time.Sleep(time.Second * 10)
    opsFinal := atomic.LoadUint64(&ops)
    fmt.Println("ops",opsFinal)

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末八毯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瞄桨,更是在濱河造成了極大的恐慌宪彩,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讲婚,死亡現(xiàn)場(chǎng)離奇詭異尿孔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門活合,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)雏婶,“玉大人,你說(shuō)我怎么就攤上這事白指×敉恚” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵告嘲,是天一觀的道長(zhǎng)错维。 經(jīng)常有香客問(wèn)我,道長(zhǎng)橄唬,這世上最難降的妖魔是什么赋焕? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮仰楚,結(jié)果婚禮上隆判,老公的妹妹穿的比我還像新娘。我一直安慰自己僧界,他們只是感情好侨嘀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捂襟,像睡著了一般咬腕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上葬荷,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天郎汪,我揣著相機(jī)與錄音,去河邊找鬼闯狱。 笑死煞赢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的哄孤。 我是一名探鬼主播照筑,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瘦陈!你這毒婦竟也來(lái)了凝危?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤晨逝,失蹤者是張志新(化名)和其女友劉穎蛾默,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捉貌,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡支鸡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年冬念,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牧挣。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡急前,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瀑构,到底是詐尸還是另有隱情裆针,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布寺晌,位于F島的核電站世吨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏呻征。R本人自食惡果不足惜耘婚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望怕犁。 院中可真熱鬧,春花似錦己莺、人聲如沸奏甫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)阵子。三九已至,卻和暖如春胜蛉,著一層夾襖步出監(jiān)牢的瞬間挠进,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工誊册, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留领突,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓案怯,卻偏偏與公主長(zhǎng)得像君旦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嘲碱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容