golang线程池ants四种使用方法小结

 更新时间:2026年07月08日 09:22:44   作者:棉花糖_码农夜读  
本文主要介绍了golang线程池ants四种使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1、ants介绍

众所周知,goroutine相比于线程来说,更加轻量、资源占用更少、无线程上下文切换等优势,但是也不能无节制的创建使用,如果系统中开启的goroutine过多而没有及时回收,也会造成系统内存资源耗尽。

ants是一款高性能的协程管理池,实现了协程的创建、缓存、复用、刷新、停止等功能,同时允许开发者设置线程池中worker的数量、线程池本身的个数以及workder中的任务,从而实现更加高效的运行效果。

2、使用方式汇总

ants的使用有四种方式,分别如下:

这四种使用方式,前两种最常用,基本能满足日常系统的开发需要,第四种默认池,简单的场景也可以用,但不推荐,多池的情况还没想到特别合适的应用场景。

3、各种使用方式详解

3.1 默认池

ants在启动时,会默认初始化一个协程池,这部分代码位于ants.go文件中:

var (
	// ErrLackPoolFunc will be returned when invokers don't provide function for pool.
	ErrLackPoolFunc = errors.New("must provide function for pool")

	// ErrInvalidPoolExpiry will be returned when setting a negative number as the periodic duration to purge goroutines.
	ErrInvalidPoolExpiry = errors.New("invalid expiry for pool")

	// ErrPoolClosed will be returned when submitting task to a closed pool.
	ErrPoolClosed = errors.New("this pool has been closed")

	// ErrPoolOverload will be returned when the pool is full and no workers available.
	ErrPoolOverload = errors.New("too many goroutines blocked on submit or Nonblocking is set")

	// ErrInvalidPreAllocSize will be returned when trying to set up a negative capacity under PreAlloc mode.
	ErrInvalidPreAllocSize = errors.New("can not set up a negative capacity under PreAlloc mode")

	// ErrTimeout will be returned after the operations timed out.
	ErrTimeout = errors.New("operation timed out")

	// ErrInvalidPoolIndex will be returned when trying to retrieve a pool with an invalid index.
	ErrInvalidPoolIndex = errors.New("invalid pool index")

	// ErrInvalidLoadBalancingStrategy will be returned when trying to create a MultiPool with an invalid load-balancing strategy.
	ErrInvalidLoadBalancingStrategy = errors.New("invalid load-balancing strategy")

	// workerChanCap determines whether the channel of a worker should be a buffered channel
	// to get the best performance. Inspired by fasthttp at
	// https://github.com/valyala/fasthttp/blob/master/workerpool.go#L139
	workerChanCap = func() int {
		// Use blocking channel if GOMAXPROCS=1.
		// This switches context from sender to receiver immediately,
		// which results in higher performance (under go1.5 at least).
		if runtime.GOMAXPROCS(0) == 1 {
			return 0
		}

		// Use non-blocking workerChan if GOMAXPROCS>1,
		// since otherwise the sender might be dragged down if the receiver is CPU-bound.
		return 1
	}()

	// log.Lmsgprefix is not available in go1.13, just make an identical value for it.
	logLmsgprefix = 64
	defaultLogger = Logger(log.New(os.Stderr, "[ants]: ", log.LstdFlags|logLmsgprefix|log.Lmicroseconds))

	// Init an instance pool when importing ants.
	defaultAntsPool, _ = NewPool(DefaultAntsPoolSize)
)

使用起来就比较简单了,直接往池子里提交任务即可。

package main

import (
	"fmt"
	"sync"
	"time"

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

func add(d int) {
	sum := 0
	for i := 0; i < d; i++ {
		sum += i
	}
}
func main() {
	var wg sync.WaitGroup
	now := time.Now()
	for i := 0; i < 5; i++ {
		wg.Add(1)
		ants.Submit(func() {
			add(10000000000)
			wg.Done()
		})
	}
	wg.Wait()
	fmt.Println(time.Since(now))
	now = time.Now()
	for i := 0; i < 5; i++ {
		add(10000000000)
	}
	fmt.Println(time.Since(now))
}

运行结果:

3.2 普通模式

普通模式和使用默认池非常类似,但是需要自己创建一个线程池:

p, _ := ants.NewPool(5)

函数参数为协程池协程个数,测试代码如下:

package main

import (
	"fmt"
	"sync"
	"time"

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

func add(d int) {
	sum := 0
	for i := 0; i < d; i++ {
		sum += i
	}
}
func main() {
	var wg sync.WaitGroup
	now := time.Now()
	p, _ := ants.NewPool(5)
	for i := 0; i < 5; i++ {
		wg.Add(1)
		p.Submit(func() {
			add(10000000000)
			wg.Done()
		})
	}
	wg.Wait()
	fmt.Println("协程池运行:", time.Since(now))
	now = time.Now()
	for i := 0; i < 5; i++ {
		add(10000000000)
	}
	fmt.Println("循环运行:", time.Since(now))
}

3.3 带参函数

带参函数,重点是往worker中传递函数执行的参数,每个workder中都是同一个执行函数。

package main

import (
	"fmt"
	"sync"
	"time"

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

func add(d int) {
	sum := 0
	for i := 0; i < d; i++ {
		sum += i
	}
	fmt.Println("the sum is: ", sum)
}
func main() {
	var wg sync.WaitGroup
	now := time.Now()
	p, _ := ants.NewPoolWithFunc(5, func(i interface{}) {
		add(i.(int))
		wg.Done()
	})
	for i := 0; i < 5; i++ {
		wg.Add(1)
		p.Invoke(1000000000)
	}
	wg.Wait()
	fmt.Println("循环运行:", time.Since(now))
}

运行结果:

liupeng@liupengdeMacBook-Pro ants_study % go run thread_default.go
the sum is:  499999999500000000
the sum is:  499999999500000000
the sum is:  499999999500000000
the sum is:  499999999500000000
the sum is:  499999999500000000
循环运行: 352.447333ms

3.4 多池多协程

这种模式,就是声明了多个协程池,每个池子里有多个协程在跑。

package main
import (
	"fmt"
	"sync"
	"time"
	"github.com/panjf2000/ants/v2"
)
func add(d int) {
	sum := 0
	for i := 0; i < d; i++ {
		sum += i
	}
	fmt.Println("the sum is: ", sum)
}
func main() {
	var wg sync.WaitGroup
	runTimes := 20
	now := time.Now()
	mpf, _ := ants.NewMultiPoolWithFunc(10, runTimes/10, func(i interface{}) {
		add(i.(int))
		wg.Done()
	}, ants.LeastTasks)
	for i := 0; i < runTimes; i++ {
		wg.Add(1)
		mpf.Invoke(1000000000)
	}
	wg.Wait()
	fmt.Println("循环运行:", time.Since(now))
}

运行记录:

4、总结

以上就是ants协程池所有的使用方式,3.2、3.3章节介绍的两种方式比较常用,也是推荐的使用方式,使用协程池,可以有效的控制系统硬件资源的使用,防止机器被打满,对于高并发服务非常推荐使用。

到此这篇关于golang线程池ants四种使用方法小结的文章就介绍到这了,更多相关golang线程池ants内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • golang中进行条件编译的示例详解

    golang中进行条件编译的示例详解

    条件编译顾名思义就是在编译时让代码中的一部分生效或者失效,从而控制编译时的代码执行路径,进而影响编译出来的程序的行为,下面我们就来看看如何在golang中进行条件编译吧
    2025-03-03
  • 提升编程技能:学习如何在Go语言中正确格式化时间

    提升编程技能:学习如何在Go语言中正确格式化时间

    想知道如何在Go语言中轻松地格式化时间吗?别再浪费时间了!本文将带你快速入门,让你的代码更加优雅高效,快来学习吧!
    2024-01-01
  • Go Generate 代替 Makefile使用方法详解

    Go Generate 代替 Makefile使用方法详解

    这篇文章主要为大家介绍了Go Generate 代替 Makefile使用方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • Go语言操作MySQL的知识总结

    Go语言操作MySQL的知识总结

    Go语言中的database/sql包提供了保证SQL或类SQL数据库的泛用接口,并不提供具体的数据库驱动。本文介绍了Go语言操作MySQL的相关知识,感兴趣的可以了解一下
    2022-11-11
  • 浅析Go语言中的逃逸分析

    浅析Go语言中的逃逸分析

    逃逸分析算是go语言的特色之一,所以这篇文章小编就来和大家聊聊为什么不应该过度关注go语言的逃逸分析,感兴趣的小伙伴可以跟随小编一起了解一下
    2024-10-10
  • Go语言结构体Go range的学习教程

    Go语言结构体Go range的学习教程

    这篇文章主要为大家介绍了Go语言结构体Go range的学习教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • Golang中时间戳与时区转换的方法详解

    Golang中时间戳与时区转换的方法详解

    时间是我们生活的基石,而在计算机科学中,时间处理显得尤为重要,尤其是当你在处理分布式系统、跨时区应用和全球服务时,时间和时区的管理变得不可或缺,在这篇文章中,我们将深入探讨Golang中的时间戳与时区转换,需要的朋友可以参考下
    2024-06-06
  • go单例实现双重检测是否安全的示例代码

    go单例实现双重检测是否安全的示例代码

    这篇文章主要介绍了go单例实现双重检测是否安全,本文给大家分享双重检验示例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • golang实现整型和字节数组之间的转换操作

    golang实现整型和字节数组之间的转换操作

    这篇文章主要介绍了golang实现整型和字节数组之间的转换操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go语言编程学习golang配置golint

    Go语言编程学习golang配置golint

    这篇文章主要为大家介绍了Go语言编程学习golang配置golint的过程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-11-11

最新评论