前言
线程池大家都听过,其主要解决的是线程频繁创建销毁带来的性能影响,控制线程数量。
go协程理论上支持百万协程并发,协程创建调度的消耗极低,但毕竟也是消耗对吧。
而且协程池可以做一些额外的功能,比如限制并发,定时等功能。
tunny中的协程池实现的几个功能,一个是限制并发,另一个是能根据协程上下文中断协程处理。同时能在协程处理过程中能做一些额外逻辑,算是装饰器吧。
简单示例
我们首先通过一个简单的例子来看这个协程池怎么使用,根据这个例子来一步步看源码。
pool := tunny.NewFunc(10, func(in interface{}) interface{} {
intVal := in.(int)
fmt.Println(intVal)
return intVal * 2
})
defer pool.Close()
for i := 0; i < 10; i++ {
ret := pool.Process(i)
fmt.Println(ret)
}
上例中,通过tunny.NewFunc 创建了一个容量为10的协程池,第二个参数定义了协程的处理方法,在下面的循环中,通过pool.Process(i) 调用了定义的方法,这个例子已经包含了协程池的创建和调度,来看看这两个是怎么实现的。
其他实践:
tunny
vs ants
tunny
设计的思路与ants
有较大的区别:
tunny
只支持同步的方式执行任务,虽然任务在另一个 goroutine 执行,但是提交任务的 goroutine 必须等待结果返回或超时。不能做其他事情。正是由于这一点,导致tunny
的设计稍微一点复杂,而且为了支持超时和取消,设计了多个通道用于和执行任务的 goroutine 通信。一次任务执行的过程涉及多次通信,性能是有损失的。从另一方面说,同步的编程方式更符合人类的直觉。
ants
完全是异步的任务执行流程,相比tunny
性能是稍高一些的。但是也因为它的异步特性,导致没有任务超时、取消这些机制。而且如果需要收集结果,必须要自己编写额外的代码。
总结
本文介绍了另一个 goroutine 池的实现tunny
。它以同步的方式来处理任务,编写代码更加直观,对任务的执行流程有更强的控制,如超时、取消等。当然实现也复杂一些。