Golang:限制阻塞操作的并发级别
我有以下情况: 我在一个频道上收到一条信息,告诉我上传一个文件。上传是通过阻塞函数uploadToServer进行的。zipGen频道每秒可能会收到几条消息,我希望最多同时上传5个文件,不是更多,但可能更少-这取决于第三个工作者在zipGen上发送的消息数量,这超出了本问题的范围 listenToZips函数在go例程中运行,go listenToZips位于文件的init函数上:Golang:限制阻塞操作的并发级别,go,Go,我有以下情况: 我在一个频道上收到一条信息,告诉我上传一个文件。上传是通过阻塞函数uploadToServer进行的。zipGen频道每秒可能会收到几条消息,我希望最多同时上传5个文件,不是更多,但可能更少-这取决于第三个工作者在zipGen上发送的消息数量,这超出了本问题的范围 listenToZips函数在go例程中运行,go listenToZips位于文件的init函数上: func listenToZips() { for { select {
func listenToZips() {
for {
select {
case zip := <-zipGen:
uploadToServer(zip) // this is blocking
}
}
}
如果我启动go uploadToServerzip而不是uploadToServerzip,我会获得太多的并发性,例如,我的程序将尝试同时上载10个文件,但我希望最多上载5个
另一方面,没有像上面的函数那样使用uploadToServerzip,我一次只上传一个文件,因为uploadToServerzip被阻塞了
我如何实现这种级别的控制,以允许我同时最多上载5个文件
谢谢 最简单的选项是预加载goroutine,它以循环的方式从通道获取输入并上传。在每个goroutine的上下文中,操作将被阻塞,但是N个goroutine会这样做。当然,只有一个goroutine会收到每条消息
func listenToZips(concurrent int) {
for i:=0; i < concurrent; i++ {
// spawn a listener goroutine
go func() {
for {
select {
case zip := <-zipGen:
uploadToServer(zip) // this is blocking
}
}
}()
}
}
当然,您可以添加停止条件,可能使用不同的频道,但基本思想是一样的。尝试以下方法:
我喜欢简单。谢谢@orcaman当限制非常大时,我正在使用一个更复杂的模式,并且所需的并发性可能会改变,所以如果大多数goroutine是空闲的,我不想运行恒定数量的goroutine。但是在小范围内,这是最好的选择。顺便说一下,如果select中只有一个case,不包括默认case,那么整个循环几乎与简化的:for-zip:=range-zipGen{uploadtoserver-zip}完全相同。一个不同之处是简化版更好地处理通道关闭;如果频道关闭,您的代码将忙于循环调用uploadToServernil,并尽可能快地进行调用。@DaveC感谢您发现这一点
limiter := NewConcurrencyLimiter(10)
limiter.Execute(func() {
uploadToServer()
})
limiter.Wait()