为 worker goroutine 排队项目的正确方法?
Correct way to queue items for a worker goroutine?
我正在编写一个允许用户上传文件并将其排队等待处理的应用程序。我的方法是创建一个 goroutine 来处理上传的文件,并使用一个通道来表示新文件已准备好进行处理。
基本上,处理 goroutine 是这样做的:
for {
while itemForProcessing() {
processNextItem()
}
select {
case <-signalChan:
case <-stopChan:
return
}
}
用于指示新项目已准备好进行处理的代码如下所示:
select {
case signalChan <- true:
default:
}
请注意,这是通道上的非阻塞发送。
存在三种可能的情况:
- 处理goroutine在
select{}
块中——第一个案例运行,下一个项目被处理
- 处理 goroutine 正在执行
processNextItem()
— 下一项将被处理一次 processNextItem()
returns 因为循环条件将是 true
- 处理goroutine已经退出循环但还没有进入
select{}
块
最后一种情况会导致问题。非阻塞发送不会在通道上发送任何东西,goroutine 将在 select{}
块中等待,直到发生其他事情。
如何避免这个问题?我不能使用阻塞发送,因为处理 goroutine 可能是 运行 processNextItem()
,这会导致发送阻塞很长时间。
为避免丢失信号,请使用容量为 1 的信道。
我正在编写一个允许用户上传文件并将其排队等待处理的应用程序。我的方法是创建一个 goroutine 来处理上传的文件,并使用一个通道来表示新文件已准备好进行处理。
基本上,处理 goroutine 是这样做的:
for {
while itemForProcessing() {
processNextItem()
}
select {
case <-signalChan:
case <-stopChan:
return
}
}
用于指示新项目已准备好进行处理的代码如下所示:
select {
case signalChan <- true:
default:
}
请注意,这是通道上的非阻塞发送。
存在三种可能的情况:
- 处理goroutine在
select{}
块中——第一个案例运行,下一个项目被处理 - 处理 goroutine 正在执行
processNextItem()
— 下一项将被处理一次processNextItem()
returns 因为循环条件将是true
- 处理goroutine已经退出循环但还没有进入
select{}
块
最后一种情况会导致问题。非阻塞发送不会在通道上发送任何东西,goroutine 将在 select{}
块中等待,直到发生其他事情。
如何避免这个问题?我不能使用阻塞发送,因为处理 goroutine 可能是 运行 processNextItem()
,这会导致发送阻塞很长时间。
为避免丢失信号,请使用容量为 1 的信道。