生产者完成后通知消费者

时间:2008-11-12 03:12:35

标签: producer-consumer concurrency

我正在读取ldap中的大量数据,需要将其与数据库中的相应记录进行比较。为了最大限度地减少SQL查询的数量,我想将多个ldap记录批量处理为单个查询。

所有这一切都非常简单:产生ldap结果的线程,以及使用这些结果并运行SQL查询的线程。

ldap_results = Queue.Queue(10)
def producer():
  for result in ldap_results():
    ldap_results.put(result)

def consumer():
  buffer = []
  buffer_size = 5
  while True:
    record = ldap_results.get()
    buffer.append(record)
    if len(buffer) >= buffer_size:
      do_sql(buffer)
      buffer = []

问题是:如果ldap仅返回3个结果且buffer_size为5,那么它将永远阻止。我意识到我可以在缓冲区中加入一些特殊的令牌,比如None"EOF",但这看起来很糟糕:“迭代直到你完成,哦,除非你看到这个特殊值,这意味着你也完成了。“

我提出了两个不同的想法。第一个是共享eof变量,但我不知道如何正确同步它。

def producer():
  while data:
    buffer.put()
  eof = True

def consumer():
  while not eof:
    buffer.get()

第二个是为生产者设置一个ProduceChunks(chunk_size)方法,它将处理结果的批处理,但我不喜欢这样,因为它假定生产者将知道如何最好地缓冲结果,当,真的,我认为这是消费者的责任。

有没有人有任何指导?

2 个答案:

答案 0 :(得分:1)

我会遵循“让它运行,使它正确,快速,简单”模式。

如果没有特殊的“EOF”令牌,你能正确实现吗?如果没有,那么你只需要使用EOF令牌,不要出汗。是的,终止条件更复杂,但现在它是“正确的”。

答案 1 :(得分:0)

“EOF”方法非常值得尊重。让我们看一下ANSI字符串的缩影。 null是EOF。这有什么不好的?

或者,让我们看一下BSTR的缩影。第一个字节告诉您字节的来源,而不是尾随的空值。

无论哪种方式都没问题。

没关系。