package main
import (
"fmt"
"time"
)
type GoPool struct {
MaxLimit int
tokenChan chan struct{}
}
// 定义一个函数类型(这个函数有一个入参没有返回值)
type GoPoolOption func(*GoPool)
// 动态生成一个函数,这里我将这个函数命名为并发控制函数(生成的这个函数有如下函数体:重新初始化结构体值’并发个数,令牌通道内存,通道槽位赋值‘)
func WithMaxLimit(max int) GoPoolOption {
return func(gp *GoPool){
gp.MaxLimit = max
gp.tokenChan = make(chan struct{},gp.MaxLimit)
for i:=0;i<gp.MaxLimit;i++{
gp.tokenChan <- struct{}{}
}
}
}
// 将并发控制函数做成参数传递给New函数,使用New函数生成一个运行池。
func NewGoPool(options ...GoPoolOption) *GoPool {
p := &GoPool{}
for _,o := range options{
o(p)
}
return p
}
//1、先初始化一个运行池,默认0值。
//2、在用并发控制函数对这个运行池进行规则初始化(:重新初始化结构体值’并发个数,令牌通道内存,通道槽位赋值‘)。
//3、返回这个运行池。
// 并发提交一个任务
func (gp *GoPool) Submit(fn func()){
token := <- gp.tokenChan //取到了牌子,才能去开启一个任务
go func(){ //并发
fn() //执行任务
gp.tokenChan <- token //任务执行完了,还回牌子
}()
}
// 为运行池添加Wait方法,其实我认为这个方法更合适的名字是:关闭通道 (即此方法的功能是:在每个槽位都空闲的时候关闭通道)
func (gp *GoPool) Wait(){
for i:=0 ;i<gp.MaxLimit;i++{ //只是在关闭通道之前,需要想能取到每个槽位的令牌,而要取到每个槽位的令牌就需要每个槽位都空闲。
<- gp.tokenChan
}
close(gp.tokenChan)
}
// 通道到槽位里面有几个槽位有令牌(有值)?
func (gp *GoPool) size() int {
return len(gp.tokenChan)
}
func main() {
gopool := NewGoPool(WithMaxLimit(1), WithMaxLimit(4))
defer gopool.Wait()
for i:=0;i<5;i++ {
fmt.Println("每个任何开启之前通道的大小:",gopool.size())
gopool.Submit(func() {
fmt.Println("qian",gopool.size())
time.Sleep(2 * time.Second)
fmt.Println(time.Now())
fmt.Println("hou",gopool.size())
})
}
}
golang并发控制代码 大伟注释
最新推荐文章于 2024-01-29 15:58:55 发布