go简单协程池实现

 为防止无限制开启gorouting造成的cpu性能浪费以及更严重的内存溢出和程序崩溃,这里加单实现一下协程池

深入理解:http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang/

流程图:

代码实现: 

package main

import (
	"fmt"
	"time"
)

//----------------------有关任务的功能-----------
//定义一个任务类型
type Task struct {
	f func() error //一个Task里有一个具体的业务,业务名称叫f
}

//创建一个Task任务
func NewTask(arg_f func() error) *Task {
	return &Task{f:arg_f}
}

//task执行业务的方法
func (t *Task) Execute() {
	err := t.f() //真正执行具体业务
	if err != nil {
		fmt.Println("任务出错:", err)
	}
}

//----------------------有关协程池Pool的功能-----------
//定义协程池
type Pool struct {
	//对外的task入口
	EntryChannel chan *Task
	//内部的task队列
	JobsChannel chan *Task
	//协程池中worker数量
	worker_num int
}
//创建协程池
func NewPool(cap int) *Pool{
	return &Pool{
		EntryChannel:make(chan *Task),
		JobsChannel:make(chan *Task),
		worker_num:cap,
	}
}
//协程池创建一个worker,让这个worker取队列里拿任务执行
func (p *Pool) startOneWorker(worker_ID int){
	//一直永久地从JobsChannel取任务
	for task := range p.JobsChannel {
		//取到任务后开始执行
		task.Execute()
		fmt.Println("worker_ID ",worker_ID, " 执行完了一个任务!")
	}
}
//启动协程池
func (p *Pool) run() {
	//根据worker_num创建worker
	for i := 0; i < p.worker_num; i++ {
		//启动自定数量的工人,并开始执行任务
		go p.startOneWorker(i)
	}
	//从EntryChannel中取任务,将新任务发给内部队列JobsChannel
	for task := range p.EntryChannel{
		p.JobsChannel <- task
	}
}

func main() {
	//1.创建一些任务。这里示例用循环重复一个任务
	t := NewTask(func() error {
		fmt.Println(time.Now())
		return nil
	})
	//2.创建容量为4的协程池
	p := NewPool(4)
	task_num := 0
	//3.将任务放入协程池外部接口
	go func() {
		for {
			p.EntryChannel <- t
			task_num ++
			fmt.Println("当前一个执行了 ",task_num," 个任务!")
		}
	}()
	//4.启动pool
	p.run()


}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值