網站首頁 編程語言 正文
?正文
Worker Pools
線程池是一種并發模式。該模式中維護了固定數量的多個工作器,這些工作器等待著管理者分配可并發執行的任務。該模式避免了短時間任務創建和銷毀線程的代價。
在 golang
中,我們使用 goroutine
和 channel
來構建這種模式。工作器 worker
由一個 goroutine
定義,該 goroutine
通過 channel
獲取數據。
處理CVS文件記錄
接下來讓我們通過一個例子,來進一步理解該模式。假設您需要處理來自 CVS
文件的記錄數據,我們需要將該文件中的經緯度保存到數據庫中。代碼如下。
package main import ( "encoding/csv" "fmt" "os" "time" ) type city struct { name string location string } func createCity(record city) { time.Sleep(10 * time.Millisecond) } func main() { startTime := time.Now() csvFile, err := os.Open("cities.csv") if err != nil { fmt.Println(err) } fmt.Println("Successfully Opened CSV file") defer csvFile.Close() csvLines, err := csv.NewReader(csvFile).ReadAll() if err != nil { fmt.Println(err) } counter := 0 for _, line := range csvLines { counter++ createCity(city{ name: line[0], location: line[1], }) } fmt.Println("records saved:", counter) fmt.Println("total time:", time.Since(startTime)) }
?? 獲取測試數據
cities.csv
輸出:
正如我們所看到的,保存 CSV
中所有記錄需要 55 秒,這是很長的時間,可能會導致很多性能問題。用戶如果想要上傳 CSV
文件,那體驗感一定很差。
如何解決這個問題?那我們就使用線程池的方法試試看。
線程池耗時差異
在如下示例中,我們將解決相同的需求,但通過線程池,耗時方面,我們能夠看到巨大的差異。來吧!
代碼如下
package main import ( "encoding/csv" "fmt" "os" "time" ) type city struct { name string location string } func createCity(record city) { time.Sleep(10 * time.Millisecond) } func readData(cityChn chan []city) { var cities []city csvFile, err := os.Open("cities.csv") if err != nil { fmt.Println(err) } fmt.Println("Successfully Opened CSV file") defer csvFile.Close() csvLines, err := csv.NewReader(csvFile).ReadAll() if err != nil { fmt.Println(err) } for _, line := range csvLines { cities = append(cities, city{ name: line[0], location: line[1], }) } cityChn <- cities } func worker(cityChn chan city) { for val := range cityChn { createCity(val) } } func main() { startTime := time.Now() cities := make(chan []city) go readData(cities) const workers = 5 jobs := make(chan city, 1000) for w := 1; w <= workers; w++ { go worker(jobs) } counter := 0 for _, val := range <-cities { counter++ jobs <- val } fmt.Println("records saved:", counter) fmt.Println("total time:", time.Since(startTime)) }
輸出:
你看到很大的不同了嗎?現在同樣的過程只需要 8 秒。正如您所見,當我們需要處理大量數據時,線程池非常有用。
使用線程池,我們必須定義一個函數,在示例中該函數為 worker
,該函數用于定義工作進程,您可以看到它接收一個 Channel
通道來處理數據。 另外,我們必須在數據傳遞到通道之前啟動 goroutines
協程,當 Channel
通道獲取到值時,goroutines
工作者開始處理它們。
?? 現在您知道如何實現線程池了!
原文鏈接:https://juejin.cn/post/7132421198964588575
相關推薦
- 2023-07-15 React 中的 context使用方法
- 2022-05-27 android實現簡單拼圖游戲_Android
- 2022-12-29 Kotlin?協程思維模型的引入使用建立_Android
- 2023-03-02 Python實現設置顯示屏分辨率_python
- 2022-04-18 antd4.*表格 Each child in a list should have a uniqu
- 2022-03-28 一篇文章帶你學習python的函數與類_python
- 2022-08-20 Linux常用高頻命令_linux shell
- 2022-07-30 分布式session的問題(使用SpringSession和redis解決)
- 最近更新
-
- 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同步修改后的遠程分支