2013-01-09 26 views
5

Próbuję zaimplementować wątki (z wykorzystaniem dekoratorów) do mojej aplikacji, ale nie mogę zrozumieć pewnych rzeczy na temat blokad i zarządzania wątkami.Wątki z dekoratorami

import threading 

def run_in_thread(fn): 
    def run(*k, **kw): 
     t = threading.Thread(target=fn, args=k, kwargs=kw) 
     t.start() 
    return run 

class A: 
    @run_in_thread 
    def method1(self): 
     for x in range(10000): 
      print x 


    @run_in_thread 
    def method2(self): 
     for y in list('wlkefjwfejwiefwhfwfkjshkjadgfjhkewgfjwjefjwe'): 
      print y 

    def stop_thread(self): 
     pass 

c = A() 
c.method1() 
c.method2() 
  1. Jak rozumiem, method1 i Method2 nie są zsynchronizowane, ale synchronizujący z tych rzeczy wykonawczych z pomocą zamków. Jak mogę dodać zamki do funkcji dekoratora?

  2. Jak mogę zrealizować metodę zatrzymywania długich wątków za pomocą dekoratorów?

+0

Co to jest synchronizacja między dwoma wątkami? – awatts

+0

Być może powiedziałem coś niepoprawnego. Chcę mieć możliwość w niektórych przypadkach (nie zawsze) uruchomić drugi wątek po 1 wątku, a nie równolegle. –

+0

Z pewnością prostym sposobem na to, aby nie uruchamiać kodu w wątku w tym przypadku. W takim przypadku możesz mieć dwie podobne metody, jedną, która wykonuje zadanie w wątku, a druga nie. Alternatywnie można przekazać parametr podczas wywoływania, który wskazuje, czy połączenie ma być nawiązywane, czy nie. – awatts

Odpowiedz

4

Korzystanie

def run_in_thread(fn): 
    def run(*k, **kw): 
     t = threading.Thread(target=fn, args=k, kwargs=kw) 
     t.start() 
     return t # <-- this is new! 
    return run 

pozwala na lepsza kontrole nad wątku: można zrobić potem

c = A() 
t1 = c.method1() 
t1.join() # wait for it to finish 
t2 = c.method2() 
# ... 
3
  1. Jeśli chcesz synchronizować dwa wątki wystarczy dodać blokad wewnątrz zdobione funkcji, a nie same dekoratorów.

  2. Nie istnieje prosty sposób na bezpośrednie zatrzymanie wątku, jedynym sposobem jest użycie zdarzenia do sygnalizowania wątku, który musi zostać zakończony.

Dla dekoratorów gwintowania można spojrzeć na pebble.

+0

Wygląda bardzo interesująco. – glglgl

0

Może Semafory może pomóc w dekoratorów, coś takiego - obliczanie liczby czynnikowe od 1 do 1000 :

import threading 

from functools import wraps 
from math import factorial 


DIC = {} 

def limit(number): 
    ''' This decorator limits the number of simultaneous Threads 
    ''' 
    sem = threading.Semaphore(number) 
    def wrapper(func): 
     @wraps(func) 
     def wrapped(*args): 
      with sem: 
       return func(*args) 
     return wrapped 
    return wrapper 

def async(f): 
    ''' This decorator executes a function in a Thread''' 
    @wraps(f) 
    def wrapper(*args, **kwargs): 
     thr = threading.Thread(target=f, args=args, kwargs=kwargs) 
     thr.start() 
    return wrapper 

@limit(10)  # Always use @limit as the outter decorator 
@async 
def calcula_fatorial(number): 
    DIC.update({number: factorial(number)}) 

@limit(10) 
def main(lista): 
    for elem in lista: 
     calcula_fatorial(elem) 


if __name__ == '__main__': 
    from pprint import pprint 
    main(range(1000)) 
    pprint(DIC)