超轻量级golang的Goroutine池

    技术2022-07-11  125

    本文是阅读GoFrame内grpool包的理解

    大致理解

    // 这是个Goroutine的 pool type Pool struct { limit int //池子中最大数量 count *gtype.Int // 当前运行的任务计数器,并发安全,郭大nb list *glist.List //异步工作的队列 closed *gtype.Bool // 是否关闭的状态 }

    两种工作方式,一种是链式操作,另一种非链式操作,这里只讲链式操作

    第一步初始化一个池子,可以设置池子的容量,默认不限制

    //初始化并返回池子的指针 func New(limit ...int) *Pool { //默认 p := &Pool{ limit: -1, count: gtype.NewInt(), list: glist.New(true), closed: gtype.NewBool(), } //有传入池子容量,赋值 if len(limit) > 0 && limit[0] > 0 { p.limit = limit[0] } return p }

    添加任务到池中

    //简单粗暴,直接传入一个闭包方法 func (p *Pool) Add(f func()) error { //判断池子是否关闭 for p.closed.Val() { return errors.New("pool closed") } //添加任务到队列中 p.list.PushFront(f) // 判断是否需要开启新的Goroutine var n int for { //获取池子运行的任务数量 n = p.count.Val() //判断当前运行的协程数量达到池子的最大容量,达到最大数量直接退出 if p.limit != -1 && n >= p.limit { // No need fork new goroutine. return nil } //未到达,跳出循环,进行fork if p.count.Cas(n, n+1) { // Use CAS to guarantee atomicity. break } } p.fork() return nil }

    fork

    //开启一个协程,完成任务的协程会被go自动回收 func (p *Pool) fork() { go func() { //退出前减少运行协程池子容量 defer p.count.Add(-1) var job interface{} //伪死循环,当清空队列中的所有任务后会退出循环以及协程 for !p.closed.Val() { //抛出队列中的随机一项任务,并执行,如果抛出为空,退出当前循环,以及协程 if job = p.list.PopBack(); job != nil { job.(func())() } else { return } } }() }

    好了,一个协程池的最主要内容就讲完了,其他的我就不讲了

    Processed: 0.011, SQL: 9