網站首頁 編程語言 正文
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一直在消費數據。
總結
通過這篇文章,我們知道了channel的概念和作用。也知道了gqueue的底層實現和特點,以及gqueue和channel的對比。兩者各有什么特點。
原文鏈接:https://juejin.cn/post/7103502362429358116
相關推薦
- 2022-07-15 python實現打印類的所有屬性和方法_python
- 2022-12-22 Python?Flask框架實現Proteus仿真Arduino與網頁數據交互_python
- 2022-10-19 python類參數定義及數據擴展方式unsqueeze/expand_python
- 2022-06-23 Windows下批處理(BAT)修改文件名的一些整理_DOS/BAT
- 2022-11-03 Python入門教程之三元運算符的使用詳解_python
- 2022-06-23 批處理腳本del命令的具體使用_DOS/BAT
- 2022-05-20 Idea搭建一個簡單的SpringBoot項目
- 2023-02-15 刪除docker中沒有被使用的數據卷volume_docker
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支