package main
import (
"fmt"
"sync"
"time"
)
type gPool struct {
taskList chan int
stop chan struct{}
wg *sync.WaitGroup
}
type groutinePool interface {
AddTask(int)
Clean()
}
func NewGroutinePool() groutinePool {
var p gPool
p.taskList = make(chan int, 1000)
p.stop = make(chan struct{})
p.wg = new(sync.WaitGroup)
for i := 0; i < 10; i++ {
p.wg.Add(1)
go func(p *gPool, i int) {
loop:
for {
select {
case task, ok := <-p.taskList:
if !ok {
break loop
}
//to do task
//假装是个耗时任务
fmt.Println("do task", task)
time.Sleep(1 * time.Second)
}
}
p.wg.Done()
fmt.Println("close worker goroutine", i)
}(&p, i)
}
return &p
}
func (p *gPool) AddTask(index int) {
p.taskList <- index
}
func (p *gPool) Clean() {
close(p.taskList)
p.wg.Wait()
}
/*
1.来个任务直接起一个协程处理->任务多的情况下会内存爆炸
2.来个任务放channel,另起一个协程消费->任务多的情况下一个协程处理不完,添加任务时会造成阻塞
3.同2方案channel加缓冲区->缓冲区满了之后还是会导致同样问题
4.channel加缓冲&应用协程池,可有效加快处理速度,并且添加任务基本不会阻塞。
*/
func main() {
p := NewGroutinePool()
for i := 0; i < 1000; i++ {
go p.AddTask(i)
}
time.Sleep(10 * time.Second)
p.Clean()
}
心血来潮写了个自己玩~~