ants:高性能的 goroutine 池库


ants 是一个高性能的 goroutine 池库,用于管理和复用 goroutine,可以有效减少 goroutine 创建和销毁的开销,提高程序性能。下面详细介绍 ants 的使用方法。


1. 安装

首先安装 ants 库:

go get -u github.com/panjf2000/ants/v2

2. 基本使用

2.1 创建 goroutine 池

package main

import (
	"fmt"
	"sync"
	"time"

	"github.com/panjf2000/ants/v2"
)

func demoFunc() {
	time.Sleep(10 * time.Millisecond)
	fmt.Println("Hello World!")
}

func main() {
	defer ants.Release()

	runTimes := 1000

	// 使用公共池
	var wg sync.WaitGroup
	syncCalculateSum := func() {
		demoFunc()
		wg.Done()
	}
	
	for i := 0; i < runTimes; i++ {
		wg.Add(1)
		_ = ants.Submit(syncCalculateSum)
	}
	wg.Wait()
	fmt.Printf("running goroutines: %d\n", ants.Running())
	fmt.Printf("finish all tasks.\n")
}

2.2 创建带容量的池

func main() {
	// 设置池容量为10
	p, _ := ants.NewPool(10)
	defer p.Release()

	for i := 0; i < 100; i++ {
		p.Submit(func() {
			fmt.Printf("Task %d is running\n", i)
			time.Sleep(1 * time.Second)
		})
	}

	// 等待所有任务完成
	time.Sleep(5 * time.Second)
}

3. 高级功能

3.1 带参数的函数

func main() {
	p, _ := ants.NewPool(10)
	defer p.Release()

	var wg sync.WaitGroup
	task := func(i int) func() {
		return func() {
			fmt.Printf("Task %d is running\n", i)
			time.Sleep(1 * time.Second)
			wg.Done()
		}
	}

	for i := 0; i < 100; i++ {
		wg.Add(1)
		p.Submit(task(i))
	}

	wg.Wait()
}

3.2 自定义池选项

func main() {
	options := ants.Options{
		ExpiryDuration: 10 * time.Second, // worker的过期时间
		PreAlloc:       true,             // 是否预分配内存
		Nonblocking:    false,            // 是否非阻塞模式
		MaxBlockingTasks: 100,            // 最大阻塞任务数
		PanicHandler: func(interface{}) { // panic处理函数
			fmt.Println("Recover from panic")
		},
	}
	
	p, _ := ants.NewPoolWithOptions(1000, options)
	defer p.Release()

	// 使用池...
}

3.3 非阻塞模式

func main() {
	p, _ := ants.NewPool(2, ants.WithNonblocking(true))
	defer p.Release()

	for i := 0; i < 5; i++ {
		err := p.Submit(func() {
			time.Sleep(1 * time.Second)
			fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
		})
		if err != nil {
			fmt.Printf("task %d submit failed: %v\n", i, err)
		}
	}

	time.Sleep(3 * time.Second)
}

4. 性能调优

4.1 池大小设置

  • 计算密集型任务:建议设置为 CPU 核心数
  • IO密集型任务:可以设置更大的值,如 CPU 核心数的 2-5 倍
p, _ := ants.NewPool(runtime.NumCPU())

4.2 监控池状态

fmt.Printf("Pool Capacity: %d\n", p.Cap())
fmt.Printf("Running Goroutines: %d\n", p.Running())
fmt.Printf("Free Goroutines: %d\n", p.Free())

5. 注意事项

  1. 及时释放池:使用 defer p.Release() 确保池被正确释放
  2. 错误处理:检查 Submit 方法的返回值,处理可能的错误
  3. 任务隔离:池中的任务应该是相互独立的,避免共享状态
  4. panic处理:为池设置 PanicHandler 防止单个任务 panic 影响整个程序

6. 完整示例

package main

import (
	"fmt"
	"sync"
	"time"

	"github.com/panjf2000/ants/v2"
)

func main() {
	// 创建带选项的池
	p, err := ants.NewPoolWithOptions(10, ants.Options{
		ExpiryDuration: time.Minute,
		PreAlloc:       true,
		PanicHandler: func(recovered interface{}) {
			fmt.Printf("Recovered from panic: %v\n", recovered)
		},
	})
	if err != nil {
		panic(err)
	}
	defer p.Release()

	var wg sync.WaitGroup

	// 带参数的任务
	task := func(id int) {
		defer wg.Done()
		fmt.Printf("Task %d started\n", id)
		time.Sleep(time.Second)
		if id == 5 {
			panic("simulated panic")
		}
		fmt.Printf("Task %d completed\n", id)
	}

	// 提交任务
	for i := 0; i < 20; i++ {
		wg.Add(1)
		id := i
		err := p.Submit(func() { task(id) })
		if err != nil {
			fmt.Printf("Failed to submit task %d: %v\n", id, err)
			wg.Done()
		}
	}

	wg.Wait()

	// 打印池状态
	fmt.Printf("Pool Capacity: %d\n", p.Cap())
	fmt.Printf("Running Workers: %d\n", p.Running())
	fmt.Printf("Free Workers: %d\n", p.Free())
}

ants 库通过复用 goroutine 显著提高了高并发场景下的性能,减少了内存分配和 GC 压力。合理配置池大小和选项可以使其在不同场景下发挥最佳效果。

posted @ 2025-06-04 14:21  guanyubo  阅读(144)  评论(0)    收藏  举报