您好,登錄后才能下訂單哦!
本篇內容介紹了“goFrame的隊列gqueue對比channel使用實例分析”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
首先明確一下channel的作用:用于go協程間的通信。
go語言最大的特點就是支持高并發:goroutine和channel是支持高并發的重要組成部分。
單純地將函數并發執行是沒有意義的。函數與函數間需要交換數據才能體現并發執行函數的意義。
如果說 goroutine 是Go程序并發的執行體,channel
就是它們之間的連接。channel
是可以讓一個 goroutine 發送特定值到另一個 goroutine 的通信機制。
另外要明確知道go的并發哲學,銘記這句原則:用通信來共享內存,而不要用共享內存來通信。
在搞清楚channel的作用之后我們再來研究GoFrame框架(下文簡稱gf)中gqueue的特點。
隊列 gqueue 動態大小的并發安全隊列
gqueue也可以設置為固定大小的隊列,固定大小時和標準庫channel沒區別。
簡單來說channel實現的功能gqueue也能實現。
gqueue是并發安全的,常用于多個goroutine數據通信且支持動態隊列大小的場景
package main import ( "fmt" "github.com/gogf/gf/container/gqueue" "github.com/gogf/gf/os/gtimer" "time" ) func main() { //實例化gqueue q := gqueue.New() //數據生產者 每隔1秒想隊列寫入1條數據 gtimer.SetInterval(time.Second, func() { nowStr := time.Now().String() q.Push(nowStr) }) //3秒后關閉隊列 gtimer.SetTimeout(time.Second*3, func() { fmt.Println("關閉隊列") q.Close() }) // 消費者 不停的從隊列中取值輸出到終端中 for { if v := q.Pop(); v != nil { fmt.Println("消費者接收:", v) } else { break } } }
為什么不用標準庫的channel,要用gqueue呢?
gqueue的使用比channel更靈活,channel有隊列大小的限制,而gqueue隊列支持動態大小
channel的讀寫性能確實非常高,但是channel創建的時候需要初始化內存,初始化操作效率非常低;而gqueue的創建效率非常高,gqueue是動態創建內存。
gqueue的底層實現是基于glist實現動態大小的特性,在隊列滿或者隊列空時讀取數據會產生阻塞。
glist是一個并發安全的鏈接,支持關閉并發安全的特性,當關閉并發安全的特性時和普通鏈表無異,在存儲和讀取數據時,不會產生阻塞。
select{}的作用可以阻止進程銷毀
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() { //實例化隊列 queue := gqueue.New() // 生產者每隔1秒鐘向隊列寫入一條數據 gtimer.SetInterval(time.Second, func() { queue.Push(gtime.Now().String()) }) //消費者 常駐內存一直接收生產者的數據 for { select { case v := <-queue.C: //C是 chan interface{} if v != nil { fmt.Println("消費者:", v) } else { return } } } }
如下圖所示,select{}可以阻止進程銷毀,gtimer一直在生產數據,而for循環中的select一直在消費數據。
“goFrame的隊列gqueue對比channel使用實例分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。