我有一个线程,它将行附加到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
答案 0 :(得分:11)
你的主要任务是否正在使用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时原始代码存在竞争问题(例如,在设置标志之前可能会将多个项目附加到队列中,从而导致代码在第一)。更新了来自ΤΖΩΤΖΙΟΥ的建议 - 生产者线程应该在队列中附加一个特殊标记(已完成)以表明它已完成。
注意:如果您有多个生产者线程,则需要更通用的方法来检测它们何时完成。您可以使用相同的策略完成此操作 - 每个线程都是Finished标记,而消费者在看到num_threads标记时终止。
答案 1 :(得分:1)
使用信号量;让工作线程在完成后释放它,并阻止你的追加线程直到工人完成信号量。
即。在工作人员中,在工作开始时执行self.done = threading.Semaphore()
之类的操作,并在完成时执行self.done.release()
。在上面提到的代码中,只需执行self.done.acquire()
,而不是繁忙循环;当工作线程完成时,控制权将返回。
编辑:我担心我没有解决你所需的超时值;这个issue描述了标准库中信号量超时的必要性。
答案 2 :(得分:0)
使用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
答案 3 :(得分:0)
您必须在此处使用同步原语。看这里:http://docs.python.org/library/threading.html。
事件对象看起来非常简单,应该可以解决您的问题。您还可以使用条件对象或信号量。
我没有发布一个例子,因为我从未使用过Event对象,替代方案可能不那么简单。
编辑:我不确定我理解你的问题。如果线程可以等到某个条件得到满足,则使用同步。否则,有人发布的sleep()
解决方案会占用太多的CPU时间。
答案 4 :(得分:0)
使用互斥模块或事件/信号量