我有一个线程,它将行附加到self.output,并运行一个循环,直到self.done为True(或达到最大执行时间)。

除了使用不断检查以查看是否已完成的while循环之外,是否有更有效的方法来执行此操作。 while循环导致CPU在运行时加速到100%。

time.clock()
while True:

    if len(self.output):
        yield self.output.pop(0)

    elif self.done or 15 < time.clock():
        if 15 < time.clock():
            yield "Maximum Execution Time Exceeded %s seconds" % time.clock()
        break
有帮助吗?

解决方案

你的主要任务是否正在使用self.output?如果是这样,这是 Queue.Queue 的量身定制的工作。您的代码应该类似于:

import Queue

# Initialise queue as:
queue = Queue.Queue()
Finished = object()   # Unique marker the producer will put in the queue when finished

# Consumer:
try:
    while True:
        next_item = self.queue.get(timeout=15)
        if next_item is Finished: break
        yield next_item

except Queue.Empty:
    print "Timeout exceeded"

您的生产者线程使用 queue.put(item)

将项添加到队列中

[编辑] 检查self.done时原始代码存在竞争问题(例如,在设置标志之前可能会将多个项目附加到队列中,从而导致代码在第一)。更新了&#932;&#918;&#937;&#932;&#918;&#921;&#927;&#933; - 生产者线程应该在队列中附加一个特殊的令牌(已完成)以表明它已完成。

注意:如果您有多个生产者线程,则需要更通用的方法来检测它们何时完成。您可以使用相同的策略完成此操作 - 每个线程都是Finished标记,而消费者在看到num_threads标记时终止。

其他提示

使用信号量;让工作线程在完成时释放它,并阻止你的追加线程直到工人完成信号量。

即。在worker中,在工作开始时执行类似 self.done = threading.Semaphore()的操作,完成后执行 self.done.release()。在上面提到的代码中,只需执行 self.done.acquire();而不是繁忙循环。当工作线程完成时,控制权将返回。

编辑:我担心我没有解决你所需的超时值;此问题描述了标准库中信号量超时的必要性。

使用time.sleep(seconds)在while循环的每次迭代后创建一个短暂的暂停以放弃cpu。您必须根据在完成作业后快速捕获作业的重要性来设置每次迭代时间的睡眠时间。

示例:

time.clock()
while True:

    if len(self.output):
        yield self.output.pop(0)

    elif self.done or 15 < time.clock():
        if 15 < time.clock():
            yield "Maximum Execution Time Exceeded %s seconds" % time.clock()
            break

    time.sleep(0.01) # sleep for 10 milliseconds

使用互斥模块或事件/信号量

您必须在此处使用同步原语。请看这里: http://docs.python.org/library/threading.html

事件对象看起来非常简单,应该可以解决您的问题。您还可以使用条件对象或信号量。

我没有发布一个例子,因为我从未使用过Event对象,替代方案可能不那么简单。


编辑:我不确定我理解你的问题。如果线程可以等到某个条件得到满足,则使用同步。否则,有人发布的 sleep()解决方案会占用太多的CPU时间。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top