Golang协程池ants使用笔记

最近工程中遇到goroutine滥用导致的bug,采用了ants协程池来解决。
github-ants官方源码和使用说明

记录一个例子

go 复制代码
package main

import (
	"fmt"
	"runtime"

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

// 模拟一个任务:求数字x的平方
func square(x int, ch chan int) {
	fmt.Printf("Calculate: %d x %d = %d\n", x, x, x*x)
	ch <- x * x // 用channel存放返回值
	close(ch)
}

func main() {
	fmt.Println(runtime.GOMAXPROCS(0))
	numTask := 10
	poolSize := 3
	// 申请一个协程池对象
	pool, _ := ants.NewPoolWithFunc(poolSize, func(i interface{}) {
		arr := i.([]interface{}) // 先转为数组,再挨个取出元素填入到任务函数的参数
		square(arr[0].(int), arr[1].(chan int))
	})
	defer pool.Release() // 记得关闭协程池

	// 要执行n次任务,每个任务的返回值用channle接收
	chanReceivers := make([]chan int, numTask)
	for i := 0; i < numTask; i++ {
		chanReceivers[i] = make(chan int) // 注意这里用的是无缓冲区的channel
	}
	// 由于ants提交任务是阻塞的,所以放在routine中执行
	go func() {
		for i := 0; i < numTask; i++ {
			err := pool.Invoke([]interface{}{i, chanReceivers[i]}) // 提交任务,超过容量时会阻塞在这
			if err != nil {
				fmt.Println("[Error] Failed to invoke task: ", err)
			}
			fmt.Println("Submitted task ", i)
		}
	}()

	// 读取channel中的返回值
	for _, ch := range chanReceivers {
		// 如果通过ch发现某一任务出了错,可以直接在这里return,子协程会都被终止,避免继续做无用功。
		fmt.Println("Received:", <-ch)
	}

	fmt.Println("Done")
}
相关推荐
Android系统攻城狮15 分钟前
C++进阶之操作符重载函数operator[]:用法实例(四百三十五)
开发语言·c++
hour_go25 分钟前
TCP/IP协议相关知识点
网络·笔记·网络协议·tcp/ip
SundayBear28 分钟前
嵌入式进阶:C语言内联汇编
c语言·开发语言·汇编
零千叶42 分钟前
【面试】Java JVM 调优面试手册
java·开发语言·jvm
liulilittle1 小时前
VGW 虚拟路由器ARP剖析
开发语言·c++·编程语言·路由·sd·sdn·vgw
潘达斯奈基~1 小时前
在使用spark的applyInPandas方法过程中,遇到类型冲突问题如何解决
大数据·笔记
鸡吃丸子1 小时前
Next.js 入门指南
开发语言·javascript·next.js
wjs20241 小时前
《Foundation 滑块:界面设计的艺术与科学》
开发语言
William_cl2 小时前
【C# OOP 入门到精通】从基础概念到 MVC 实战(含 SOLID 原则与完整代码)
开发语言·c#·mvc
我先去打把游戏先2 小时前
ESP32学习笔记(基于IDF):IOT应用——WIFI连接
笔记·单片机·嵌入式硬件·mcu·物联网·学习·esp32