“什么?”你问,“这个头衔没有任何意义。”
请考虑以下情况:具有不同ID的作业可能是异步处理的,但具有相同ID的作业应该从队列中按顺序同步处理。
我当前的实现创建了一个go例程来处理每个特定id的作业,看起来像这样:
func FanOut() chan<- *Job {
channel := make(chan *Job)
routines = make(map[string]chan<- *Job)
go func() {
for j := range channel {
r, found := routines[j.id]
if !found {
r = Routine()
routines[j.id] = r
}
r <- j
}
}()
return channel
}
这似乎运作良好(在当前的测试中),但创建成千上万的例行程序可能不是最好的方法?此外,扇出代码块除非使用缓冲通道。
我正在考虑使用sync.Mutex的集合而不是go例程的集合(上图)。这个想法是拥有一个go例程池,它必须首先在与作业id相对应的互斥锁上建立锁定。
是否有适合处理这些要求的现有Go模式?
有更好的方法吗?
为每个ID创建一个通道 - 可能是一段通道或一个地图(由ID索引)。每个通道都有一个go-routine,按顺序处理该ID的作业。简单。
我不担心创造太多的常规。我不会使用互斥锁 - 如果没有使用通道进入太多细节,并且go-routines允许每个作业一次只能由一个例程处理,并避免数据竞争的可能性。
顺便说一下,我只是添加了这个作为答案,因为我不允许添加评论(但是?)。