20 października 2016

[python] Prosty skrypt z uruchomieniem wątku.

Jak mówi Internet CPython w związku z istnieniem mechanizmu Global Interpreter Lock (GIL) nie pozwala na wykonanie więcej niż jednego wątku:
CPython implementation detail: In CPython, due to the Global Interpreter Lock, only one thread can execute Python code at once (even though certain performance-oriented libraries might overcome this limitation). If you want your application to make better use of the computational resources of multi-core machines, you are advised to use multiprocessing or concurrent.futures.ProcessPoolExecutor. However, threading is still an appropriate model if you want to run multiple I/O-bound tasks simultaneously.
Niemniej jednak Python posiada stosowne API, które da się wykorzystać w innym interpreterze bez ograniczeń GIL, albo przy zadaniach typu I/O.

Queue (kolejka) zapewnia bezpieczny mechanizm do wymiany informacji pomiędzy wątkami.
  • Każde zawołanie Queue.put() zwiększa licznik, który jest dekrementowany w momencie zawołania Queue.task_done().
  • Główny wątek jest blokowany przez Queue.join(), do momentu, gdy wszystkie elementy z kolejki zostaną przetworzone.
  • Funkcja Queue.get() jest domyślnie blokująca, tzn. wątek zawiesza działania, jeżeli nie ma już danych do przetworzenia.
  • Thread.daemon - wszystkie wątki potomne zostaną zabite wraz z wątkiem głównym.
Często po wywołaniu programu na konsoli pojawia się informacja o wystąpieniu wyjątku. Jest to związane ustawieniem daemon=true. Interpreter nie zdążył z czystym zamknięciem wątku gdy kończony jest wątek główny. Rozwiązaniem byłby mechanizm w samum wątku, pozwalający na jego zakończenie, gdy nie jest on już potrzebny. W przypadku prostych skryptów, raczej nie trzeba się tym przejmować.
# -*- coding: utf-8 -*-

from Queue import Queue
from threading import Thread, current_thread

def worker():
    while True:
        item = q.get()
        print current_thread().name + ': ' + str(item[0] + item[1])
        q.task_done()

q = Queue()
num_worker_threads = 3

for i in range(num_worker_threads):
    t = Thread(target=worker)
    t.daemon = True
    t.start()

for item in [(1, 2), (4, 7), (5, 2)]:
    q.put(item)

q.join()
Wynik:
Thread-2: 3
Thread-2: 11
Thread-3: 7

Brak komentarzy:

Prześlij komentarz