go 协程池

package main

import (
    "fmt"
    "log"
    "strconv"
    "sync"
)

//定义任务接口
type Runnable interface {
    run()
}

//具体任务,实现任务接口
type Task struct {
    name string //任务数据
    fun func(string)    //任务回调方法
}

//工作协程
type Worker struct {
    id       string        //线程id
    taskQueue   chan Runnable //协程要执行的任务通道
    wg *sync.WaitGroup  //等待协程结束
}


//协程池
type WorkerPool struct {
    workersSize    int            //最大协程数量
    workers      []*Worker        //所有协程
    jobQueue      chan Runnable   //等待执行的任务通道
    workerDispatcher chan *Worker      //协程分发器
    wg sync.WaitGroup               //等待协程池结束
}


//任务方法
func (task *Task) run() {
    task.fun(task.name)
}

//启动协程
func (w *Worker) Start() {
    //开一个新的协程
    go func() {
        for {
            select {
            //从任务通道中获得一个任务执行,如果通道中没有任务则线程阻塞。
            case wJob,ok := <- w.taskQueue:{
                if ok {
                    //执行任务
                    wJob.run()
                }else{
                    //协程通道关闭,协程结束
                    w.wg.Done()
                    return
                }
            }
            }
        }
    }()
}

//停止协程
func (w *Worker) Stop() {
    close(w.taskQueue)
}


//新建一个协程对象
func (pool *WorkerPool) newWorker(Id string, taskChSize int) *Worker {
    log.Printf("新建线程:%s \n", Id)
    return &Worker{
        id:Id,      //id
        taskQueue:   make(chan Runnable, taskChSize), //协程任务通道
        wg:&pool.wg,
    }
}

//新建协程池
func NewPool(maxWorkers, workerTaskSize, maxQueue int) *WorkerPool {
    JobQueue := make(chan Runnable, maxQueue)
    workerQueue := make(chan *Worker, maxWorkers)

    pool := WorkerPool{
        workersSize:    maxWorkers,
        jobQueue:      JobQueue,
        workerDispatcher: workerQueue,
        wg:sync.WaitGroup{},
    }
    pool.init(workerTaskSize)

    return &pool
}

//初始化协程池中的协程
func (pool *WorkerPool) init(workerTaskSize int) {
    // 开始运行
    for i := 0; i < pool.workersSize; i++ {
        worker := pool.newWorker(fmt.Sprintf("work-%s", strconv.Itoa(i)), workerTaskSize)
        pool.workers = append(pool.workers,worker)
        pool.workerDispatcher <- worker
        //开始工作
        worker.Start()
    }

    pool.wg.Add(pool.workersSize)

    //监控
    go pool.start()
}

//启动协程池
func (pool *WorkerPool) start() {
    for {
        select {
        case wJob, Ok := <-pool.jobQueue:
            if Ok {
                worker := <- pool.workerDispatcher
                worker.taskQueue <- wJob
                pool.workerDispatcher <- worker
            } else {
                for _,worker := range pool.workers{
                    worker.Stop()
                }
                return
            }
        }
    }
}

//添加任务
func (pool *WorkerPool) addTask(job Runnable) {
    pool.jobQueue <- job
}

//协程池结束
func (pool *WorkerPool) shutdown() {
    close(pool.jobQueue)
    pool.wg.Wait()
}

func main() {
    //新建协程池
    pool := NewPool(2, 10, 100)
    //添加100个任务
    for i := 0; i < 5; i++ {
        task := Task{fmt.Sprintf("任务%d", i+1),func(p string){log.Println(p,"执行完成")}}
        pool.addTask(&task)
        log.Println("添加任务",i)
    }

    //关闭协程池,会等待任务结束
    pool.shutdown()

}
2018/09/12 18:57:30 新建线程:work-0 
2018/09/12 18:57:30 新建线程:work-1 
2018/09/12 18:57:30 添加任务 0
2018/09/12 18:57:30 添加任务 1
2018/09/12 18:57:30 添加任务 2
2018/09/12 18:57:30 添加任务 3
2018/09/12 18:57:30 添加任务 4
2018/09/12 18:57:30 任务1 执行完成
2018/09/12 18:57:30 任务3 执行完成
2018/09/12 18:57:30 任务5 执行完成
2018/09/12 18:57:30 任务2 执行完成
2018/09/12 18:57:30 任务4 执行完成

Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/maosijunzi/article/details/82666539