package utl import ( "time" ) type WorkPoolOption func(*WorkPool) func WithWorkPoolSize(size int) WorkPoolOption { return func(wp *WorkPool) { if size < 1 { size = 64 } wp.size = size } } func WithWorkPoolLifetime(lifetime time.Duration) WorkPoolOption { if lifetime < 1*time.Second { lifetime = 1 * time.Second } return func(wp *WorkPool) { wp.lifetime = lifetime } } type WorkPool struct { goChan chan chan func(*time.Timer) size int lifetime time.Duration } func NewWorkPool(options ...WorkPoolOption) *WorkPool { wp := &WorkPool{} for _, opt := range options { opt(wp) } wp.goChan = make(chan chan func(*time.Timer), wp.size) return wp } func (wp *WorkPool) Put(f func(*time.Timer)) { for len(wp.goChan) > 0 { goRun := <-wp.goChan if goRun == nil { continue } select { case <-goRun: default: goRun <- f return } } goRun := make(chan func(*time.Timer), 1) goRun <- f go wp.do(goRun) } // in goroutine func (wp *WorkPool) do(one chan func(*time.Timer)) { defer func() { if e := recover(); e != nil { } }() timer := time.NewTimer(time.Second * 1) defer timer.Stop() for { select { case <-timer.C: close(one) f, ok := <-one if !ok { return } f(timer) return case f, ok := <-one: if !ok { return // one 可能关闭 } f(timer) timer.Reset(time.Second * 10) } // reuse if len(wp.goChan) < wp.size { wp.goChan <- one } } //for }