本文是閱讀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
}
}
}()
}
好了,一個協程池的最主要内容就講完了,其他的我就不講了