2009-04-30 24 views
9

Tengo un hilo que agrega filas a self.output y un bucle que se ejecuta hasta que self.done es True (o se alcanza el tiempo máximo de ejecución).Python - Threading y un while True Loop

Hay una manera más eficiente de hacer esto que no sea usar un ciclo while que comprueba constantemente si está hecho. El bucle while hace que la CPU pico a 100% mientras se está ejecutando ..

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 

Respuesta

11

¿Sus hilos se anexan a self.output aquí, con su tarea principal consumiéndolos? Si es así, este es un trabajo hecho a medida para Queue.Queue. El código debe ser algo así como:

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" 

Sus hilos productores agregan elementos a la cola con queue.put(item)

[Editar] El código original tiene un problema de la raza en la comprobación self.done (por ejemplo, varios elementos se puede anexar a la cola antes de que se establezca la bandera, lo que hace que el código se resquebraje en la primera). Actualizado con una sugerencia de ΤΖΩΤΖΙΟΥ - el hilo del productor debería agregar un token especial (Finalizado) a la cola para indicar que está completo.

Nota: Si tiene varios hilos de productor, necesitará un enfoque más general para detectar cuando estén terminados.Puede lograr esto con la misma estrategia: cada hilo un marcador Terminado y el consumidor termina cuando ve marcadores num_threads.

+0

OoOooo, ahora estamos hablando. : D – Ian

+0

¿Hay alguna manera de decirle a un bloqueo de subprocesos en un Queue.get() sin un tiempo de espera que el productor termine de poner algo en el hilo para que pueda salir limpiamente? – millimoose

+0

@Sii: Puede marcar el hilo daemonic cuando lo crea. Esto significa que el hilo se cerrará cuando salga tu programa. –

0

Uso time.sleep (segundos) para crear una breve pausa después de cada iteración del bucle while para renunciar a la CPU. Tendrá que establecer el tiempo que duerme durante cada iteración en función de la importancia de captar el trabajo rápidamente después de que esté completo.

Ejemplo:

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

dormir generalmente resulta en un mal rendimiento. deberías considerar la sincronización antes de usar los sueños. – Francis

0

Usted tiene que usar una primitiva de sincronización aquí. Mire aquí: http://docs.python.org/library/threading.html.

Los objetos del evento parecen muy simples y deberían resolver su problema. También puede usar un objeto de condición o un semáforo.

No publico un ejemplo porque nunca he usado objetos de evento, y las alternativas son probablemente menos simples.


Editar: No estoy muy seguro de haber entendido su problema. Si un hilo puede esperar hasta que se confirme alguna condición, use la sincronización. De lo contrario, la solución sleep() que alguien haya publicado tomará demasiado tiempo de CPU.

0

módulo de uso mutex o evento/semáforo

1

uso de un semáforo; haga que el hilo de trabajo lo suelte cuando haya terminado, y bloquee el hilo anexado hasta que el trabajador haya terminado con el semáforo.

es decir. en el trabajador, haga algo como self.done = threading.Semaphore() al comienzo del trabajo, y self.done.release() cuando termine. En el código que anotó anteriormente, en lugar del bucle ocupado, simplemente haga self.done.acquire(); cuando el subproceso de trabajo finaliza, el control volverá.

Editar: Me temo que no abordo el valor de tiempo de espera necesario; este issue describe la necesidad de un tiempo de espera de semáforo en la biblioteca estándar.