Go 协程池

并发处理task,限制goroutine数量

package main                                                                                                                                                 

import (
    "fmt"
    "sync"
    "time"
)

type Task struct {
    f func() error
}

func NewTask(f func() error) *Task {
    t := Task{
        f: f,
    }   
    return &t
}

func (t *Task) Execute() {
    t.f()
}

type Pool struct {
    EntryChan chan *Task
    WorkNum   int 
    JobChan   chan *Task
    Wg        *sync.WaitGroup
}

func NewPool(cap int) *Pool {
    p := Pool{
        EntryChan: make(chan *Task),
        JobChan:   make(chan *Task),
        WorkNum:   cap,
        Wg:        &sync.WaitGroup{},
    }
    return &p
}

func (p *Pool) Worker(id int) {
    defer p.Wg.Done()                    //单个goroutine处理完业务,如果测试defer可以跳出for,如开10个协程,设置超时时间,超时或执行完当前任务直接退出for,回
收当前go
    timer := time.After(time.Second * 6) // timer
    exitFlag := false
    for {
        select {
        case job, ok := <-p.JobChan:
            if ok {
                job.Execute()
                fmt.Println("work id:", id, "执行成功", job)
                exitFlag = true
            }
        case <-timer:
            fmt.Println("work timeout,id:", id)
            exitFlag = true
        default:
            fmt.Println("work job chan no data,waiting...")
            time.Sleep(1 * time.Second)
        }
        if exitFlag {
            fmt.Println("work done,id:", id)
            break
        }
    }
}

func (p *Pool) Send(t *Task) {
    p.EntryChan <- t
}

func (p *Pool) Run() {
    for i := 0; i < p.WorkNum; i++ {
        p.Wg.Add(1)
        go p.Worker(i)
    }
    timer := time.After(time.Second * 10) // timer,监听输入,一般不做超时,循环接受任务
    exitFlag := false
    for {
        select {
        case task, ok := <-p.EntryChan:
            if ok {
                p.JobChan <- task
                fmt.Println("read task to job:", task)
            }
        case <-timer:
            fmt.Println("timeout no read")
            exitFlag = true
        default:
            fmt.Println("entry chan have no data,in run waiting...")
            time.Sleep(1 * time.Second)
        }
        if exitFlag {
            fmt.Println("break receive task")
            break
        }
    }
    close(p.JobChan)
    close(p.EntryChan)
}

func main() {
    t1 := NewTask(func() error {
        fmt.Println("matrix 11, t1")
        return nil
    })
    t2 := NewTask(func() error {
        fmt.Println("matrix 12,t2")
        time.Sleep(time.Second * 30)
        return nil
    })
    t3 := NewTask(func() error {
        fmt.Println("matrix 13,t3")
        return nil
    })
    t4 := NewTask(func() error {
        fmt.Println("matrix 14,t4")
        time.Sleep(time.Second * 6)
        return nil
    })
    p := NewPool(10)
    go func() {
        p.Send(t1)
        p.Send(t2)
        p.Send(t3)
        p.Send(t4)
    }()
    p.Run()
    p.Wg.Wait()
    fmt.Println("all done...")
}

http://t.csdnimg.cn/IPJlG

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 Go 语言中,协程是轻量级的线程,可以在同一个进程中同时运行成百上千个协程,而不会导致系统资源的过度占用。协程是一种常见的编程模式,它可以有效地管理协程的数量,减少协程的创建和销毁操作。 下面是一个简单的协程实现: ```go type Worker struct { id int taskQueue chan func() quit chan bool } func NewWorker(id int, taskQueue chan func(), quit chan bool) Worker { return Worker{ id: id, taskQueue: taskQueue, quit: quit, } } func (w Worker) Start() { go func() { for { w.taskQueue <- <- w.taskQueue select { case task := <- w.taskQueue: task() case <- w.quit: return } } }() } type Pool struct { workers []Worker taskQueue chan func() quit chan bool } func NewPool(size int) Pool { workers := make([]Worker, size) taskQueue := make(chan func()) quit := make(chan bool) for i := 0; i < size; i++ { workers[i] = NewWorker(i, taskQueue, quit) } return Pool{ workers: workers, taskQueue: taskQueue, quit: quit, } } func (p Pool) Start() { for _, worker := range p.workers { worker.Start() } } func (p Pool) Stop() { close(p.quit) } func (p Pool) Submit(task func()) { p.taskQueue <- task } ``` 使用方法如下: ```go func main() { pool := NewPool(4) pool.Start() for i := 0; i < 10; i++ { index := i pool.Submit(func() { fmt.Println("Task", index) }) } pool.Stop() } ``` 这个例子中,我们创建了一个协程,大小为 4。然后我们提交了 10 个任务,每个任务都只是简单地打印一条消息。协程会自动管理协程的数量,保持在指定的大小范围内。 需要注意的是,这个实现中并没有考虑协程执行任务的顺序和优先级,如果需要这些特性,需要对代码进行进一步的扩展。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值