2009-04-30 2 views
9

У меня есть поток, который добавляет строки в self.output и цикл, который выполняется до тех пор, пока self.done не будет True (или не будет достигнуто максимальное время выполнения).Python - Threading и while True Loop

Есть ли более эффективный способ сделать это, кроме использования цикла while, который постоянно проверяет, выполнено ли это. Цикл пока вызывает процессор пронзать до 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 

ответ

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)

[Edit] Исходный код имеет проблемы гонки при проверке self.done (например, несколько элементов может быть добавлено в очередь до того, как будет установлен флаг, в результате чего код выйдет из строя на первом). Обновленный с предложением от ΤΖΩΤΖΙΟΥ - поток производителя должен вместо этого добавить специальный токен (законченный) в очередь, чтобы указать, что он завершен.

Примечание. Если у вас несколько потоков производителей, вам понадобится более общий подход к обнаружению, когда все будет готово.Вы можете выполнить это с помощью той же стратегии: каждый поток, маркер завершен, и потребитель прекращает свое действие, когда видит маркеры num_threads.

+0

OoOooo, теперь мы говорим. : D – Ian

+0

Есть ли способ рассказать о блокировке потока на Queue.get() без тайм-аута, который производитель сделал, помещая что-нибудь в поток, чтобы он мог выйти чисто? – millimoose

+0

@Sii: Вы можете отметить поток демонов при его создании. Это означает, что поток выйдет, когда ваша программа выйдет. –

0

Использование time.sleep (в секундах), чтобы создать небольшую паузу после каждой итерации цикла в то время отказаться от процессора. Вам нужно будет установить время, когда вы спите во время каждой итерации, исходя из того, насколько важно, чтобы вы быстро поймали работу после ее завершения.

Пример:

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 
+0

Сон обычно приводит к плохим результатам. вы должны рассмотреть синхронизацию перед использованием спит. – Francis

0

Вы должны использовать примитив синхронизации здесь. Смотрите здесь: http://docs.python.org/library/threading.html.

Объекты мероприятия кажутся очень простыми и должны решить вашу проблему. Вы также можете использовать объект условия или семафор.

Я не отправляю пример, потому что я никогда не использовал объекты Event, и альтернативы, вероятно, менее просты.


Edit: Я не совсем уверен, что я понял вашу проблему. Если поток может ждать, пока какое-либо условие будет выполнено, используйте синхронизацию. В противном случае решение sleep(), которое кто-то разместил, займет слишком много времени процессора.

0

модуль использовать мьютекс или событие/семафор

1

Использование семафор; чтобы рабочая нить освободила его, когда закончилась, и заблокируйте добавочный поток, пока рабочий не закончит семафор.

ie. в рабочем, сделайте что-то вроде self.done = threading.Semaphore() в начале работы, и self.done.release() по окончании. В коде, который вы указали выше, вместо цикла занятости, просто сделайте self.done.acquire(); когда рабочий поток будет завершен, управление вернется.

Редактировать: Я боюсь, что я не адресую ваше требуемое значение таймаута; этот issue описывает необходимость тайм-аута семафора в стандартной библиотеке.