Python - 线程与无限循环

10 投票
5 回答
16055 浏览
提问于 2025-04-15 11:20

我有一个线程,它会把行添加到 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

5 个回答

0

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

1

使用信号量;让工作线程在完成后释放它,并让你的添加线程在工作线程完成之前保持阻塞状态。

也就是说,在工作线程中,开始工作时可以写类似 self.done = threading.Semaphore() 的代码,完成时则用 self.done.release()。在你提到的代码中,别用忙等的方式,直接用 self.done.acquire();当工作线程完成后,控制权就会返回。

补充:我担心我没有解决你需要的超时值;这个 问题 描述了标准库中信号量超时的需求。

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),来表示它已经完成。

注意:如果你有多个生产者线程,你需要一种更通用的方法来检测它们是否都完成。你可以用同样的策略——每个线程添加一个Finished标记,消费者在看到num_threads个标记时就结束。

撰写回答