如何重用 Goroutine 而不是创建新的 Goroutine 来实现异步调用

问题描述 投票:0回答:1

对于这个用例,它似乎可能是有效的: 这是简单的代码,但你应该明白 -

func Log(v interface{}){

  1. get json - json marshal some large object v
  2. write big buf to a file 

}

上面的代码可能会非常阻塞,所以也许想放入一个 goroutine:

func Log(v interface{}){

  go func(){
    1. get json - json marshal some large object v
    2. write big buf to a file (not necessarily stdout)
  }()
}

但问题是我们在这里创建了很多 goroutine,这可能会违背将其放入 goroutine 的目的。

所以我的问题是 - 有没有办法以某种方式使用 goroutine 池,并使用它们。即使 10 个人在一个泳池里就已经很棒了。

我假设使用渠道与他们沟通,但不确定具体如何

两个规定:

  1. 一次仅将 1 个作业添加到队列中
  2. 如果队列已满,我只想单独运行它,而不是向队列添加新的工作人员
go asynchronous goroutine pool
1个回答
0
投票

Prelim、非测试工作池,具有以下功能:

  1. 一次仅添加 1 个职位
  2. 如果没有可用的worker,我们就生成自己的goroutine

请戳个洞,我确信锁定不太正确



    package pool
    
    import "sync"
    
    type Worker struct {
        c      chan func()
        mtx    sync.Mutex
        isBusy bool
    }
    
    type Pool struct {
        mtx               *sync.Mutex
        Size              int
        workers           []*Worker
        Count             int
        RoundRobinCounter int
    }
    
    func (p *Pool) createWorkers() {
        for i := 0; i < p.Size; i++ {
        
            var w = &Worker{
                c:      make(chan func(), 1),
                mtx:    sync.Mutex{},
                isBusy: false,
            }

            go func(v chan func()) {
                for {
                    var f = <-v
                    w.mtx.Lock()
                    w.isBusy = true
                    p.Count++
                    f()
                    p.Count--
                    w.isBusy = false
                    w.mtx.Unlock()
                }
            }(c)
            p.workers = append(p.workers)
        }
    }
    
    func CreatePool(size int) *Pool {
    
        var p = &Pool{
            Size:              size,
            Count:             0,
            RoundRobinCounter: size + 1,
        }
    
        p.createWorkers()
    
        return p
    }
    
    func (p *Pool) GoPool(z func()) {
    
        p.mtx.Lock()
    
        if p.Count >= p.Size {
            p.mtx.Unlock()
            // queue is full, so just create a new goroutine here
            go z()
            return
        }
    
        for _, v := range p.workers {
            if !v.isBusy {
                v.mtx.Lock()
                p.mtx.Unlock()
                v.isBusy = true
                v.c <- z
                v.mtx.Unlock()
                return
            }
        }
    
        p.mtx.Unlock()
    
        // couldn't find a non-busy one, so just round robin to next
        p.RoundRobinCounter = (p.RoundRobinCounter + 1) % p.Size
        var v = p.workers[p.RoundRobinCounter]
        v.mtx.Lock()
        v.c <- z
        v.mtx.Unlock()
    
    }

© www.soinside.com 2019 - 2024. All rights reserved.