goFrame的隊列gqueue對比channel使用詳解
channel
首先明確一下channel的作用:用於go協程間的通信。
go語言最大的特點就是支持高並發:goroutine和channel是支持高並發的重要組成部分。
單純地將函數並發執行是沒有意義的。函數與函數間需要交換數據才能體現並發執行函數的意義。
如果說 goroutine 是Go程序並發的執行體,channel
就是它們之間的連接。channel
是可以讓一個 goroutine 發送特定值到另一個 goroutine 的通信機制。
另外要明確知道go的並發哲學,銘記這句原則:用通信來共享內存,而不要用共享內存來通信。
在搞清楚channel的作用之後我們再來研究GoFrame框架(下文簡稱gf)中gqueue的特點。
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使用詳解的詳細內容,通過這篇文章,我們知道瞭channel的概念和作用。也知道瞭gqueue的底層實現和特點,以及gqueue和channel的對比。兩者各有什麼特點,更多關於goFrame gqueue對比channel的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- GoFrame glist 基礎使用和自定義遍歷
- GoFrame框架garray對比PHP的array優勢
- GoFrame基於性能測試得知grpool使用場景
- GoFrame gtree樹形結構的使用技巧示例
- GoFrame框架gredis優雅的取值和類型轉換