如何用golang写一个thread pool
来源:互联网 发布:虚拟机装mac os 编辑:程序博客网 时间:2024/06/05 01:22
我的工作目标
1 创建一个指定大小的工作数据2 实现run接口3 添加任务到池子里面4 开始运行池子
首先定义任务的worker和runner接口
package workpooltype Runner interface { Run(interface{}) (interface{}, error)}type Work struct { Runner Runner Args interface{}}func NewWork(runner Runner, args interface{}) *Work { return &Work{runner, args}}
我使用了两张方式定义了pool
1 使用go的list
2 使用chan
1 使用go的list,基本思想启动几个go协程,是不停的从list里面读取数据,当然这里面用到了锁
package workpoolimport ( "container/list" "log" "sync" "time")//工作池type Kworkpool struct { rmutex sync.RWMutex mutex sync.Mutex //写锁 runnerList *list.List //任务列表 poolSize int //启动的pool的个数 flag bool //是否关闭}//新建一个池子func NewKworkpool(size int) *Kworkpool { l := list.New() return &Kworkpool{ poolSize: size, flag: true, runnerList: l, }}//添加数据func (kl *Kworkpool) AddRunner(w *Work) { if kl.flag { kl.runnerList.PushFront(w) }}func (kl *Kworkpool) Start() { if !kl.flag { kl.Close() return } kl.run()}//启动多个goroutinefunc (kl *Kworkpool) run() { for i := 0; i < kl.poolSize; i++ { go kl.work() }}//实际的工作脚本运行poolfunc (kl *Kworkpool) work() { for { //检测数据的长度 kl.rmutex.RLock() listLen := kl.runnerList.Len() kl.rmutex.RUnlock() if listLen == 0 { //休眠100毫秒 //已经关闭就结束程序,需要判断是否已经没有任务 if !kl.flag { break } time.Sleep(time.Millisecond * 100) continue } kl.mutex.Lock() elem := kl.runnerList.Back() if elem == nil { kl.mutex.Unlock() continue } worker := kl.runnerList.Remove(elem).(*Work) kl.mutex.Unlock() log.Println(" start running ...") worker.Runner.Run(worker.Args) }}func (kl *Kworkpool) Close() { kl.flag = false}func init() { log.SetFlags(log.LstdFlags)}
使用chan实现,本质上是使用chan代替list,使用WaitGroup等待所有协程的结束
package workpoolimport ( "log" "sync")//工作池type KworkpoolChan struct { agroup sync.WaitGroup works chan *Work //一个chan processSize int //启动的work pool的个数 flag bool //是否关闭}//新建一个池子func NewKworkpoolChan(poolSize, processSize int) *KworkpoolChan { pool := &KworkpoolChan{ works: make(chan *Work, poolSize), processSize: processSize, flag: true, } pool.Start() return pool}//添加数据func (kl *KworkpoolChan) AddRunner(w *Work) { //发送数据到chan if kl.flag { kl.works <- w } log.Println("works_len =", len(kl.works))}func (kl *KworkpoolChan) Start() { if !kl.flag { kl.Close() return } kl.agroup.Add(kl.processSize) for i := 0; i < kl.processSize; i++ { go func() { for runWorker := range kl.works { runWorker.Runner.Run(runWorker.Args) } kl.agroup.Done() }() }}func (kl *KworkpoolChan) Close() { if kl.flag != false { kl.flag = false } close(kl.works) //等待所有线程完成任务 kl.agroup.Wait()}
测试代码
package mainimport ( "fmt" "log" "os" "strconv" "time" "workpool")//测试runnertype Arunner struct {}func (a *Arunner) Run(avar interface{}) (interface{}, error) { i := avar.(int) filename := "./log/" + strconv.Itoa(time.Now().Nanosecond()) fp, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, os.ModePerm) if err != nil { log.Println("go", i) return nil, err } fp.WriteString("go" + strconv.Itoa(i) + "\n") fp.Close() return nil, nil}func main() { tpool2()}func tpool2() { //test pool 2 var run1, run2 workpool.Runner run1 = &Arunner{} run2 = &Arunner{} pool2 := workpool.NewKworkpoolChan(8, 20) w1 := workpool.NewWork(run1, 1) w2 := workpool.NewWork(run2, 2) pool2.AddRunner(w1) pool2.AddRunner(w2) fmt.Println(pool2) time.Sleep(time.Second * 5)}func tpool1() { //test pool 1 pool := workpool.NewKworkpool(20) pool.Start() var run1, run2 workpool.Runner run1 = &Arunner{} run2 = &Arunner{} w1 := workpool.NewWork(run1, 1) w2 := workpool.NewWork(run2, 2) pool.AddRunner(w1) pool.AddRunner(w2) fmt.Print(pool)}
代码的github路径
https://github.com/beckbikang/go_pool
阅读全文
0 0
- 如何用golang写一个thread pool
- 如何用Python写一个贪吃蛇
- 如何用javascript写一个贪吃蛇
- 如何用Swing写一个时钟?
- 如何用C++写一个类
- 如何用CSS写一个三角形
- 如何用 Latex 写一个漂亮简历
- 如何用Scapy写一个端口扫描器?
- 如何用Java写一个交换函数
- 如何用Cocos2d-android写一个小游戏
- 如何用C#写一个简单的Login窗口
- 如何用C#写一个简单的Login窗口
- 如何用C#写一个简单的Login窗口
- 如何用自定义标签写一个查询数据库的Table?
- 如何用C#写一个简单的Login窗口
- 如何用C#写一个简单的Login窗口
- 如何用C#写一个简单的Login窗口
- 如何用C#写一个简单的Login窗口
- 142. Linked List Cycle II
- Java中,既然double类型比float类型,表示的数值范围更大,大家都用double类型不就行了,Java还发明float类型干什么?因为占内存少于double,其他没有任何优势了
- PCA为什么使用协方差矩阵
- 如何调试Cocos2d-JS和Cocos2d-Lua工程
- STM32 boot跳转到APP的Jump_Address()分析
- 如何用golang写一个thread pool
- vue 实现 pager 组件翻页效果
- 1019. 数字黑洞 (20)
- spark-streaming集成Kafka工程实例【转】
- 蓝牙协议分析(8)_BLE安全机制之白名单
- 《Drools 7 规则引擎教程》番外篇-规则条件匹配机制
- 11-03
- Network in Network
- 小试牛刀-递归下降算法(1)