goFrame的隊(duì)列g(shù)queue對(duì)比channel使用詳解
channel
首先明確一下channel的作用:用于go協(xié)程間的通信。
go語(yǔ)言最大的特點(diǎn)就是支持高并發(fā):goroutine和channel是支持高并發(fā)的重要組成部分。
單純地將函數(shù)并發(fā)執(zhí)行是沒(méi)有意義的。函數(shù)與函數(shù)間需要交換數(shù)據(jù)才能體現(xiàn)并發(fā)執(zhí)行函數(shù)的意義。
如果說(shuō) goroutine 是Go程序并發(fā)的執(zhí)行體,channel
就是它們之間的連接。channel
是可以讓一個(gè) goroutine 發(fā)送特定值到另一個(gè) goroutine 的通信機(jī)制。
另外要明確知道go的并發(fā)哲學(xué),銘記這句原則:用通信來(lái)共享內(nèi)存,而不要用共享內(nèi)存來(lái)通信。
在搞清楚channel的作用之后我們?cè)賮?lái)研究GoFrame框架(下文簡(jiǎn)稱(chēng)gf)中g(shù)queue的特點(diǎn)。
gqueue
概念
隊(duì)列 gqueue 動(dòng)態(tài)大小的并發(fā)安全隊(duì)列
gqueue也可以設(shè)置為固定大小的隊(duì)列,固定大小時(shí)和標(biāo)準(zhǔn)庫(kù)channel沒(méi)區(qū)別。
簡(jiǎn)單來(lái)說(shuō)channel實(shí)現(xiàn)的功能gqueue也能實(shí)現(xiàn)。
使用場(chǎng)景:
gqueue是并發(fā)安全的,常用于多個(gè)goroutine數(shù)據(jù)通信且支持動(dòng)態(tài)隊(duì)列大小的場(chǎng)景
代碼演示
package main import ( "fmt" "github.com/gogf/gf/container/gqueue" "github.com/gogf/gf/os/gtimer" "time" ) func main() { //實(shí)例化gqueue q := gqueue.New() //數(shù)據(jù)生產(chǎn)者 每隔1秒想隊(duì)列寫(xiě)入1條數(shù)據(jù) gtimer.SetInterval(time.Second, func() { nowStr := time.Now().String() q.Push(nowStr) }) //3秒后關(guān)閉隊(duì)列 gtimer.SetTimeout(time.Second*3, func() { fmt.Println("關(guān)閉隊(duì)列") q.Close() }) // 消費(fèi)者 不停的從隊(duì)列中取值輸出到終端中 for { if v := q.Pop(); v != nil { fmt.Println("消費(fèi)者接收:", v) } else { break } } } 復(fù)制代碼
打印結(jié)果
優(yōu)勢(shì)
為什么不用標(biāo)準(zhǔn)庫(kù)的channel,要用gqueue呢?
- gqueue的使用比channel更靈活,channel有隊(duì)列大小的限制,而gqueue隊(duì)列支持動(dòng)態(tài)大小
- channel的讀寫(xiě)性能確實(shí)非常高,但是channel創(chuàng)建的時(shí)候需要初始化內(nèi)存,初始化操作效率非常低;而gqueue的創(chuàng)建效率非常高,gqueue是動(dòng)態(tài)創(chuàng)建內(nèi)存。
底層實(shí)現(xiàn)
gqueue的底層實(shí)現(xiàn)是基于glist實(shí)現(xiàn)動(dòng)態(tài)大小的特性,在隊(duì)列滿或者隊(duì)列空時(shí)讀取數(shù)據(jù)會(huì)產(chǎn)生阻塞。
glist是一個(gè)并發(fā)安全的鏈接,支持關(guān)閉并發(fā)安全的特性,當(dāng)關(guān)閉并發(fā)安全的特性時(shí)和普通鏈表無(wú)異,在存儲(chǔ)和讀取數(shù)據(jù)時(shí),不會(huì)產(chǎn)生阻塞。
阻止進(jìn)程銷(xiāo)毀
select{}的作用可以阻止進(jìn)程銷(xiāo)毀
package main import ( "fmt" "github.com/gogf/gf/container/gqueue" "github.com/gogf/gf/os/gtime" "github.com/gogf/gf/os/gtimer" "time" ) func main() { //實(shí)例化隊(duì)列 queue := gqueue.New() // 生產(chǎn)者每隔1秒鐘向隊(duì)列寫(xiě)入一條數(shù)據(jù) gtimer.SetInterval(time.Second, func() { queue.Push(gtime.Now().String()) }) //消費(fèi)者 常駐內(nèi)存一直接收生產(chǎn)者的數(shù)據(jù) for { select { case v := <-queue.C: //C是 chan interface{} if v != nil { fmt.Println("消費(fèi)者:", v) } else { return } } } } 復(fù)制代碼
運(yùn)行結(jié)果
如下圖所示,select{}可以阻止進(jìn)程銷(xiāo)毀,gtimer一直在生產(chǎn)數(shù)據(jù),而for循環(huán)中的select一直在消費(fèi)數(shù)據(jù)。
總結(jié)
以上就是goFrame的gqueue對(duì)比channel使用詳解的詳細(xì)內(nèi)容,通過(guò)這篇文章,我們知道了channel的概念和作用。也知道了gqueue的底層實(shí)現(xiàn)和特點(diǎn),以及gqueue和channel的對(duì)比。兩者各有什么特點(diǎn),更多關(guān)于goFrame gqueue對(duì)比channel的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go獲取兩個(gè)時(shí)間點(diǎn)時(shí)間差的具體實(shí)現(xiàn)
本文主要介紹了Go獲取兩個(gè)時(shí)間點(diǎn)時(shí)間差的具體實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04Go標(biāo)準(zhǔn)庫(kù)-ServeMux的使用與模式匹配深入探究
這篇文章主要為大家介紹了Go標(biāo)準(zhǔn)庫(kù)-ServeMux的使用與模式匹配深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01Golang信號(hào)量設(shè)計(jì)實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了Golang信號(hào)量設(shè)計(jì)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08詳解Go語(yǔ)言中用 os/exec 執(zhí)行命令的五種方法
這篇文章主要介紹了Go語(yǔ)言中用 os/exec 執(zhí)行命令的五種方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11Go語(yǔ)言同步等待組sync.WaitGroup結(jié)構(gòu)體對(duì)象方法詳解
這篇文章主要為大家介紹了Go語(yǔ)言同步等待組sync.WaitGroup結(jié)構(gòu)體對(duì)象方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08掌握Golang中的select語(yǔ)句實(shí)現(xiàn)并發(fā)編程
Golang中的select語(yǔ)句用于在多個(gè)通道間選擇可讀或可寫(xiě)的操作,并阻塞等待其中一個(gè)通道進(jìn)行操作??梢杂糜趯?shí)現(xiàn)超時(shí)控制、取消和中斷操作等。同時(shí),select語(yǔ)句支持default分支,用于在沒(méi)有任何通道可操作時(shí)執(zhí)行默認(rèn)操作2023-04-04