Go 并發(fā)控制利器 ants 使用方法與實(shí)踐
1.ants基礎(chǔ)應(yīng)用
https://github.com/panjf2000/ants

1.1 什么是ants
ants 是一個(gè)高性能的 Go 語言 goroutine 池,它能復(fù)用已完成任務(wù)的 goroutine,避免頻繁創(chuàng)建和銷毀 goroutine,節(jié)省 CPU 與內(nèi)存開銷,并且能限制并發(fā)數(shù)量防止資源被耗盡。
1.2 安裝
go get -u github.com/panjf2000/ants/v2
1.3 最簡(jiǎn)單的例子
package main
import (
"fmt"
"time"
"github.com/panjf2000/ants/v2"
)
func main() {
// 創(chuàng)建一個(gè)容量為 10 的 goroutine 池
pool, _ := ants.NewPool(10)
defer pool.Release() // 程序結(jié)束釋放資源
// 提交任務(wù)
for i := 0; i < 20; i++ {
n := i
_ = pool.Submit(func() {
fmt.Printf("Task %d running\n", n)
time.Sleep(time.Second)
})
}
fmt.Println("All tasks submitted")
time.Sleep(3 * time.Second) // 等待任務(wù)執(zhí)行完
}
特點(diǎn):
- 同時(shí)最多只有 10 個(gè)任務(wù)運(yùn)行。
- 其余任務(wù)排隊(duì)等待空閑 worker。
2. 進(jìn)階篇
2.1 核心 API
| 方法 | 作用 |
|---|---|
| ants.NewPool(size, options...) | 創(chuàng)建一個(gè)普通任務(wù)池 |
| ants.NewPoolWithFunc(size, func, options...) | 創(chuàng)建一個(gè)綁定任務(wù)處理函數(shù)的池 |
| Submit(task) | 提交任務(wù)到池 |
| Invoke(param) | 提交參數(shù),調(diào)用綁定函數(shù) |
| Running() | 當(dāng)前正在運(yùn)行的 worker 數(shù)量 |
| Free() | 當(dāng)前空閑 worker 數(shù)量 |
| Cap() | 池容量 |
| Tune(size) | 動(dòng)態(tài)調(diào)整容量 |
| Release() | 釋放所有資源 |
| Reboot() | 重啟一個(gè)已釋放的池 |
2.2 常用配置項(xiàng)
ants.WithPreAlloc(true) // 預(yù)先分配內(nèi)存,減少運(yùn)行時(shí)分配
ants.WithNonblocking(true) // worker 不夠時(shí)立即返回錯(cuò)誤,而不是等待
ants.WithMaxBlockingTasks(1000) // 最大等待任務(wù)數(shù)
ants.WithPanicHandler(func(err interface{}) {
fmt.Println("panic:", err) // 捕獲任務(wù)中的 panic
})
ants.WithExpiryDuration(time.Second * 10) // 空閑 worker 過期時(shí)間
2.3PoolWithFunc用法
package main
import (
"fmt"
"github.com/panjf2000/ants/v2"
"time"
)
func main() {
// 定義處理函數(shù)
handler := func(data interface{}) {
fmt.Printf("Processing: %v\n", data)
time.Sleep(time.Millisecond * 500)
}
// 創(chuàng)建綁定函數(shù)的池
pool, _ := ants.NewPoolWithFunc(5, handler)
defer pool.Release()
for i := 0; i < 10; i++ {
_ = pool.Invoke(i) // 直接傳參數(shù)
}
}
3. 實(shí)戰(zhàn)篇
3.1 批量任務(wù)執(zhí)行
場(chǎng)景:你需要批量處理 10000 條數(shù)據(jù),但不希望一次性開 10000 個(gè) goroutine。
package main
import (
"fmt"
"sync"
"time"
"github.com/panjf2000/ants/v2"
)
func processTask(id int) {
fmt.Printf("Task %d start\n", id)
time.Sleep(time.Second)
fmt.Printf("Task %d done\n", id)
}
func main() {
var wg sync.WaitGroup
pool, _ := ants.NewPool(50) // 控制并發(fā)為 50
defer pool.Release()
for i := 0; i < 10000; i++ {
wg.Add(1)
taskID := i
_ = pool.Submit(func() {
defer wg.Done()
processTask(taskID)
})
}
wg.Wait()
}
3.2 HTTP 并發(fā)控制
爬取多個(gè) URL,但限制同時(shí)請(qǐng)求的數(shù)量。
package main
import (
"fmt"
"net/http"
"sync"
"github.com/panjf2000/ants/v2"
)
func fetch(url string) {
resp, err := http.Get(url)
if err != nil {
fmt.Println(err)
return
}
defer resp.Body.Close()
fmt.Println(url, resp.StatusCode)
}
func main() {
urls := []string{
"https://golang.org",
"https://github.com",
"https://google.com",
}
var wg sync.WaitGroup
pool, _ := ants.NewPool(5)
defer pool.Release()
for _, url := range urls {
wg.Add(1)
u := url
_ = pool.Submit(func() {
defer wg.Done()
fetch(u)
})
}
wg.Wait()
}
4. 最佳實(shí)踐與注意事項(xiàng)
適合長(zhǎng)時(shí)間運(yùn)行的服務(wù)
- 在任務(wù)密集的服務(wù)中能顯著降低內(nèi)存占用。
任務(wù)不宜過大或阻塞太久
- 單個(gè)任務(wù)阻塞會(huì)占用 worker,影響吞吐量。
panic 處理必須配置
- 避免單個(gè)任務(wù)導(dǎo)致池崩潰。
選擇合適的池大小
- 一般為
CPU核數(shù) * N,N 根據(jù) IO 密集度調(diào)整。
- 一般為
性能對(duì)比
- 對(duì)于少量任務(wù),直接開 goroutine 可能更快;
- 對(duì)于大規(guī)模并發(fā),
ants會(huì)明顯減少 GC 壓力。
到此這篇關(guān)于Go 并發(fā)控制利器 ants 使用文檔的文章就介紹到這了,更多相關(guān)Go 并發(fā)控制利器 ants內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
goland 實(shí)現(xiàn)自動(dòng)格式化代碼
Go基礎(chǔ)教程系列之import導(dǎo)入包(遠(yuǎn)程包)和變量初始化詳解
GoLang channel底層代碼實(shí)現(xiàn)詳解
Go標(biāo)準(zhǔn)庫之Requests的介紹與基本使用
15個(gè)Golang中時(shí)間處理的實(shí)用函數(shù)
Go基礎(chǔ)教程系列之WaitGroup用法實(shí)例詳解

