golang线程池【简易版】

mb6063e31623ab7 · · 720 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

先上代码,有兴趣的可以跑一下

可以实现在有限的线程里执行多个任务,控制内存使用,防止内存飙高

package main

import ("context""fmt""strconv""sync""time")// 定义静态变量 用于外部访问内部方法var pool *_Pool// 定义空结构体,相当于类,和下面组合New方法起来就是pool类的静态方法type _Pool struct {
}// 定义接口 可传任意参数type TaskFunc func(args ...interface{})// 定义任务实体,里面有方法和参数type Task struct {
    f    TaskFunc
    args interface{}
}// 定义线程池对象type WorkPool struct {
    Pool       chan *Task      //定义任务池WorkCount  int             //工作线程数量,决定初始化几个goroutineStopCtx    context.Context //上下文    StopCancel context.CancelFunc
    WG         sync.WaitGroup //阻塞计数器}//任务执行func (t *Task) Execute(args ...interface{}) {
    t.f(args...)
}// 实例化一个新线程池func (*_Pool) New(workerCount int, len int) *WorkPool {return &WorkPool{
        WorkCount: workerCount,
        Pool:      make(chan *Task, len),
    }
}// 任务入队func (w *WorkPool) PushTask(task *Task) {
    w.Pool <- task
}// 任务调度 go协程从channel里取任务执行Execute方法func (w *WorkPool) Work(wid int) {for {select {case <-w.StopCtx.Done():
            w.WG.Done()
            fmt.Printf("线程%d 退出执行了 \n", wid)returncase t := <-w.Pool:if t != nil {
                t.Execute()
                fmt.Printf("f被线程%d执行了,参数为%v \n", wid, t.args)
            }

        }
    }

}//启动线程池,触发任务调度func (w *WorkPool) Start() *WorkPool {//定义好worker数量    w.WG.Add(w.WorkCount)
    w.StopCtx, w.StopCancel = context.WithCancel(context.Background())for i := 0; i < w.WorkCount; i++ {//定义多少个协程来工作        go w.Work(i)
    }return w
}// 停止执行任务,回收正在执行任务的协程 协程计数器减1 直到变成0退出,否则阻塞func (w *WorkPool) Stop() {
    w.StopCancel()
    w.WG.Wait()
}
func main() {// 任务计数器taskWg := sync.WaitGroup{}
    workerCount := 2taskCount := 10// 启动线程池 len=channel通道容量,超过容量生产者阻塞,容量变成0 消费者阻塞pool := pool.New(workerCount, 5).Start()
    taskWg.Add(taskCount)//构建任务 放入线程池for i := 0; i < taskCount; i++ {
        task := &Task{
            args: "zhangSan" + strconv.FormatInt(int64(i), 10),
            f: func(args ...interface{}) {
                time.Sleep(time.Second)
                taskWg.Done() // 任务完成计数器减一            },
        }
        pool.PushTask(task)
    }

    fmt.Println("任务入队完成")//等待任务执行完成    taskWg.Wait()// 回收资源    close(pool.Pool)
    fmt.Println("任务全部执行完成")
}

 

运行效果

f被线程0执行了,参数为zhangSan0 
f被线程1执行了,参数为zhangSan1 
f被线程1执行了,参数为zhangSan3 
f被线程0执行了,参数为zhangSan2 
任务入队完成
f被线程0执行了,参数为zhangSan5 
f被线程1执行了,参数为zhangSan4 
f被线程1执行了,参数为zhangSan7 
f被线程0执行了,参数为zhangSan6 
f被线程1执行了,参数为zhangSan8 
任务全部执行完成

 

里面代码注释的很详细了,就不赘述了


有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:mb6063e31623ab7

查看原文:golang线程池【简易版】

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

720 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传