Domanda

Ho un thread che aggiunge le righe a self.output e un ciclo che funziona fino a quando self.done è True (o viene raggiunto il tempo massimo di esecuzione).

Esiste un modo più efficiente per farlo oltre all'utilizzo di un ciclo while che controlla costantemente se è stato fatto. Il ciclo while fa in modo che la CPU raggiunga il 100% mentre è in esecuzione ..

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
È stato utile?

Soluzione

I tuoi thread vengono aggiunti a self.output qui, con il tuo compito principale che li consuma? In tal caso, questo è un lavoro su misura per Queue.Queue . Il tuo codice dovrebbe diventare qualcosa del tipo:

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"

I thread del produttore aggiungono elementi alla coda con queue.put(item)

[Modifica] Il codice originale presenta un problema di razza durante il controllo di self.done (ad esempio, è possibile aggiungere più elementi alla coda prima che venga impostato il flag, causando il salvataggio del codice nel il primo). Aggiornato con un suggerimento di ??O????? - il thread del produttore dovrebbe invece aggiungere un token speciale (Finito) alla coda per indicare che è completo.

Nota: se si dispone di più thread del produttore, sarà necessario un approccio più generale per rilevare quando sono stati completati. Puoi farlo con la stessa strategia: ogni thread di un marker finito e il consumatore termina quando vede marcatori num_threads.

Altri suggerimenti

Usa un semaforo; chiedi al thread di lavoro di rilasciarlo al termine e blocca il thread accodato fino a quando il lavoratore non ha terminato il semaforo.

es. nel lavoratore, fai qualcosa come self.done = threading.Semaphore () all'inizio del lavoro e self.done.release () al termine. Nel codice che hai notato sopra, invece del ciclo di occupato, fai semplicemente self.done.acquire () ; al termine del thread di lavoro, il controllo tornerà.

Modifica: temo di non rispondere al valore di timeout necessario; questo problema descrive la necessità di un timeout del semaforo nella libreria standard.

Usa time.sleep (secondi) per creare una breve pausa dopo ogni iterazione del ciclo while per abbandonare la cpu. Dovrai impostare il tempo in cui dormi durante ogni iterazione in base all'importanza che acquisisci rapidamente il lavoro dopo il completamento.

Esempio:

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

usa il modulo mutex o evento / semaforo

Devi usare una primitiva di sincronizzazione qui. Guarda qui: http://docs.python.org/library/threading.html .

Gli oggetti evento sembrano molto semplici e dovrebbero risolvere il tuo problema. Puoi anche usare un oggetto condizione o un semaforo.

Non inserisco un esempio perché non ho mai usato oggetti Event e le alternative sono probabilmente meno semplici.


Modifica: non sono davvero sicuro di aver capito il tuo problema. Se un thread può attendere fino a quando una condizione non è statisificata, utilizzare la sincronizzazione. Altrimenti la soluzione sleep () che qualcuno ha pubblicato vuole impiegare troppo tempo sulla CPU.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top