Вопрос

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

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

Решение

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

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 (например, несколько элементов могут быть добавлены в очередь до того, как будет установлен флаг, что приведет к выходу кода из строя на первом).Обновлено по предложению ΤΖΩΤΖΙΟΥ - вместо этого поток-производитель должен добавить в очередь специальный токен (Завершено), чтобы указать, что она завершена.

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

Другие советы

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

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

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

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

Пример:

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() Решение, которое кто-то опубликовал, будет занимать слишком много процессорного времени.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top