golang高性能低成本goroutine池管理插件库ants的使用

Golang高性能低成本goroutine池管理插件库ants的使用

ants logo

简介

ants库实现了一个固定容量的goroutine池,可以管理和回收大量goroutine,允许开发者限制并发程序中的goroutine数量。

特性

  • 自动管理和回收大量goroutine
  • 定期清除过期的goroutine
  • 丰富的API:提交任务、获取运行中的goroutine数量、动态调整池容量、释放池、重启池等
  • 优雅处理panic,防止程序崩溃
  • 内存使用高效,甚至可能比Go无限制goroutines实现更高性能
  • 非阻塞机制
  • 预分配内存(环形缓冲区,可选)

工作原理

流程图

ants流程图

活动图

活动图1 活动图2 活动图3 活动图4

安装

安装ants v1

go get -u github.com/panjf2000/ants

安装ants v2 (GO111MODULE=on)

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

使用示例

基本使用

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
	
	// 使用池执行任务
	for i := 0; i < runTimes; i++ {
		wg.Add(1)
		ants.Submit(func() {
			demoFunc()
			wg.Done()
		})
	}
	
	wg.Wait()
	fmt.Printf("running goroutines: %d\n", ants.Running())
	fmt.Printf("finish all tasks.\n")
}

自定义池容量

// 创建容量为10000的池
p, _ := ants.NewPool(10000)

提交任务

// 提交任务到池
ants.Submit(func(){})

运行时调整池容量

pool.Tune(1000)    // 调整容量到1000
pool.Tune(100000)  // 调整容量到100000

预分配池内存

// ants会在调用ants.NewPool时预分配整个池容量
p, _ := ants.NewPool(100000, ants.WithPreAlloc(true))

释放池

pool.Release()
// 或者带超时释放
pool.ReleaseTimeout(time.Second * 3)

重启池

// 已释放的池可以通过调用Reboot()继续使用
pool.Reboot()

完整示例

package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
	
	"github.com/panjf2000/ants/v2"
)

var sum int32

func myFunc(i interface{}) {
	n := i.(int32)
	atomic.AddInt32(&sum, n)
	fmt.Printf("run with %d\n", n)
}

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

func main() {
	defer ants.Release()
	
	runTimes := 1000
	
	// 使用池的普通池
	var wg sync.WaitGroup
	
	// 使用池执行任务
	for i := 0; i < runTimes; i++ {
		wg.Add(1)
		ants.Submit(func() {
			demoFunc()
			wg.Done()
		})
	}
	wg.Wait()
	fmt.Printf("running goroutines: %d\n", ants.Running())
	fmt.Printf("finish all tasks.\n")
	
	// 使用带函数的池
	p, _ := ants.NewPoolWithFunc(10, func(i interface{}) {
		myFunc(i)
		wg.Done()
	})
	defer p.Release()
	
	// 提交任务
	for i := 0; i < runTimes; i++ {
		wg.Add(1)
		_ = p.Invoke(int32(i))
	}
	wg.Wait()
	fmt.Printf("running goroutines: %d\n", p.Running())
	fmt.Printf("finish all tasks, result is %d\n", sum)
}

注意事项

提交到ants池的所有任务不能保证按顺序执行,因为这些任务分散在一系列并发的工作线程中,因此这些任务是并发执行的。


更多关于golang高性能低成本goroutine池管理插件库ants的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能低成本goroutine池管理插件库ants的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang高性能goroutine池管理库ants使用指南

ants是一个高性能且低成本的goroutine池实现,特别适合需要大量goroutine但希望控制资源消耗的场景。下面详细介绍ants的使用方法。

安装

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

基本使用

1. 创建goroutine池

package main

import (
	"fmt"
	"sync"
	"time"

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

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

func main() {
	defer ants.Release()

	runTimes := 1000

	// 使用公共池
	var wg sync.WaitGroup
	for i := 0; i < runTimes; i++ {
		wg.Add(1)
		ants.Submit(func() {
			demoFunc()
			wg.Done()
		})
	}
	wg.Wait()

	fmt.Printf("running goroutines: %d\n", ants.Running())
	fmt.Printf("total goroutines: %d\n", ants.Cap())
}

2. 自定义池大小

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

	for i := 0; i < 100; i++ {
		p.Submit(func() {
			demoFunc()
		})
	}

	// 获取当前正在运行的goroutine数量
	fmt.Printf("running goroutines: %d\n", p.Running())
}

高级特性

1. 带参数的函数

func demoFuncWithArgs(i int) {
	time.Sleep(1 * time.Second)
	fmt.Printf("Hello World! %d\n", i)
}

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

	for i := 0; i < 100; i++ {
		// 使用闭包传递参数
		p.Submit(func() {
			demoFuncWithArgs(i)
		})
	}
}

2. 超时控制

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

	// 带超时的提交
	err := p.Submit(func() {
		time.Sleep(2 * time.Second)
		fmt.Println("Task completed")
	})
	if err != nil {
		fmt.Println("Submit task error:", err)
	}
}

3. 动态调整池大小

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

	// 调整容量到20
	p.Tune(20)

	// 调整容量到5
	p.Tune(5)
}

性能优化建议

  1. 合理设置池大小:根据任务类型和服务器资源设置合适的池大小

    • CPU密集型任务:核心数+1
    • IO密集型任务:可以设置更大一些
  2. 复用池:避免频繁创建和销毁池

  3. 错误处理:注意处理池满时的错误

  4. 监控指标:定期检查Running()和Cap()以调整池大小

完整示例

package main

import (
	"fmt"
	"sync"
	"time"

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

func main() {
	// 创建容量为100的池,预分配内存
	p, _ := ants.NewPool(100, ants.WithPreAlloc(true))
	defer p.Release()

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

	start := time.Now()
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		p.Submit(task(i))
	}

	wg.Wait()
	fmt.Printf("All tasks done, time elapsed: %s\n", time.Since(start))
	fmt.Printf("Pool size: %d, Running workers: %d\n", p.Cap(), p.Running())
}

ants库通过复用goroutine显著降低了频繁创建和销毁goroutine的开销,特别适合高并发场景。合理使用可以显著提升程序性能并降低资源消耗。

回到顶部