2017-08-28 13 views
12

kod start.py jest jak poniżej.ten sam program, inne wyjście w module wątków

import threading 
class myThread(threading.Thread): 
     def __init__(self, threadID, name): 
       threading.Thread.__init__(self) 
       self.threadID = threadID 
       self.name = name 

     def run(self): 
       currentThreadname = threading.currentThread() 
       print "running in ", currentThreadname 

thread = myThread(1,"mythrd") 
thread.start() 

Uruchom go z pythonem dwa razy.

python start.py 
running in <myThread(mythrd, started 140461133485824)> 
python start.py 
running in <myThread(mythrd, started 140122860668672)> 

kod run.py wygląda jak poniżej.

import threading 
class myThread(threading.Thread): 
     def __init__(self, threadID, name): 
       threading.Thread.__init__(self) 
       self.threadID = threadID 
       self.name = name 

     def run(self): 
       currentThreadname = threading.currentThread() 
       print "running in ", currentThreadname 

thread = myThread(1,"mythrd") 
thread.run() 

run.py to tylko jedna linia inna niż start.py.
Teraz uruchom program run.py na dwa razy.

python run.py 
running in <_MainThread(MainThread, started 139854546364160)> 
python run.py 
running in <_MainThread(MainThread, started 139854546364160)> 

Kod startandrun.py wygląda jak poniżej.

class myThread(threading.Thread): 
    def __init__(self, threadID, name): 
     threading.Thread.__init__(self) 
     self.threadID = threadID 
     self.name = name 

    def run(self): 
     currentThreadname = threading.currentThread() 
     print "running in ", currentThreadname 

thread = myThread(1,"mythrd") 
thread.start() 
thread.run() 

Teraz uruchom również startandrun.py również dwa razy.

python startandrun.py 
running in <myThread(mythrd, started 140317119899392)> 
running in <_MainThread(MainThread, started 140317144454912)> 
python startandrun.py 
running in running in <_MainThread(MainThread, started 139980210505472)> 
<myThread(mythrd, started 139980185949952)> 

Jak JohanL powiedzieć:
Uruchamiając dwa oddzielne wątki, wszystkie zakłady są wyłączone, co do których zostanie wykonany pierwszy.
Jesteś zasadniczo pozostawiając harmonogramu do systemu operacyjnego. po raz pierwszy wykonać startandrun.py, thread.start() został wykonany przed thread.run() to spowodować wyjście:

running in <myThread(mythrd, started 140317119899392)> 
running in <_MainThread(MainThread, started 140317144454912)> 

Drugi raz wykonać startandrun.py, thread.start() został stracony po thread.run(), dlaczego nie doprowadzić do wyjścia :

running in <_MainThread(MainThread, started 140317144454912)> 
running in <myThread(mythrd, started 140317119899392)> 

zamiast

running in running in <_MainThread(MainThread, started 139980210505472)> 
<myThread(mythrd, started 139980185949952)> 
+1

Uruchamiając dwa oddzielne wątki, wszystkie zakłady są wyłączone, aby który zostanie wykonany jako pierwszy. Zasadniczo opuszczasz planowanie w systemie operacyjnym. Dlatego potrzebne są różne prymitywy synchronizacji (semafory, monitory et.c.), gdy twoje wątki uzyskują dostęp do tych samych danych. – JohanL

+0

'thread.run' nie uruchamia nowego wątku, więc ten kod prawdopodobnie nie robi tego, co myślisz, że robi. Aby rozpocząć wątek, musisz wywołać 'start'. Nie powinieneś nazywać 'run' bezpośrednio,' start' zrobi to za ciebie. Wywoływanie początku i końca służy tylko dalszemu pomyleniu każdego problemu, który próbujesz zrozumieć. Zobacz dokumentację, która jest dość jasna na temat tego: "Gdy obiekt wątku zostanie utworzony, jego aktywność musi zostać uruchomiona przez wywołanie metody start() wątku. Wywołuje to metodę run() w osobnym wątku kontroli." – pvg

Odpowiedz

4

Dzieje się tak ze względu na sposób drukowania wartości:

print "running in ", currentThreadname 

dodanie przecinka jest podobny do:

print 'running in ' # without new line at the end 
print currentThreadname 

A ponieważ dwie funkcje są uruchomione w tym samym czasie tutaj jest sposób realizacji zamówienia:

print 'running in ' # without new line FUNCTION #1 
print 'running in ' # without new line FUNCTION #2 
print currentThreadName # with new line at the end FUNCTION #1 
print currentThreadName # with new line at the end FUNCTION #2 

Spróbuj użyć jednego polecenia wydruku bez przecinków zrozumieć, jak powinno być:

def run(self): 
    currentThreadname = threading.currentThread() 
    print "running in {}".format(currentThreadname) 

ten będzie zachowywał się normalnie, ale ponieważ te dwie funkcje drukowania w tym samym czasie, można uzyskać następujące dane wyjściowe:

running in <myThread(mythrd, started 10716)>running in <_MainThread(MainThread, started 12132)> 

Tak, aby udowodnić, że to będzie działać można użyć opóźnienie między dwoma połączeniami za pomocą time.sleep():

import threading 
import time 

class myThread(threading.Thread): 
    def __init__(self, threadID, name): 
     threading.Thread.__init__(self) 
     self.threadID = threadID 
     self.name = name 

    def run(self): 
     currentThreadname = threading.currentThread() 
     print "running in {}".format(currentThreadname) 

thread = myThread(1,"mythrd") 
thread.start() 
time.sleep(0.1) 
thread.run() 

teraz widać, że masz swój pożądany wynik, ponieważ każda funkcja drukowania jednego tim e z opóźnieniem 0,1 sek w między połączeniami:

running in <myThread(mythrd, started 5600)> 
running in <_MainThread(MainThread, started 7716)> 

EDIT:

Twój problem jest dokładnie, dlaczego należy używać wielowątkowość zamiast uruchomiony ten sam wątek dwukrotnie. Podczas korzystania z wielowątkowość Możesz użyć , który będzie czekać na zakończenie wątku, a następnie kontynuować kod, lub możesz użyć threading.lock(), aby kontynuować kod, ale zablokować funkcję, która ma być używana przez jeden wątek na raz. Oto kilka przykładów:

thread.join():

thread = myThread(1, "mythrd") 
thread2 = myThread(2, "thrd2") 
thread.start() 
thread.join() # code will stop here and wait for thread to finish then continue 
thread2.run() 

threading.lock():

.... 
    def run(self): 
     with lock: # if one thread uses this lock the other threads have to wait 
      currentThreadname = threading.currentThread() 
      print "running in ", currentThreadname 

thread = myThread(1, "mythrd") 
thread2 = myThread(2, "thrd2") 
lock = threading.Lock() 
thread.start() 
thread2.run() 
# code keeps running even if there are threads waiting for the lock 
+0

Zgadzam się z początkiem (i prawdopodobnie jest to problem OP), chociaż nie sądzę, że można uzyskać wszystko, co opisujesz w jednym linijce (to znaczy, że wiersz jest zapisywany oddzielnie w strumieniu standardowym) – MacHala

+0

@MacHala Nie jest możliwe, jeśli drukują dwa wątki, ale tutaj jeden wątek ma dwie funkcje i obie funkcje są drukowane –

0

Jaka wersja Pythona wer e ty używasz? W pythonie 2 "print" nie jest bezpieczny dla wątków. Patrz: http://tech.queryhome.com/54593/is-print-thread-safe-in-python-2-6-2-7.

Jeśli wątki przełączają się podczas "drukowania", wyjścia są mieszane, tak jak to, co widzieliście.

+1

To oczywiście python 2 ze względu na składnię. I nie to oznacza "bezpieczny dla nici". – pvg

+0

@pvg, więc co to znaczy "bezpieczny wątek"? – VHao

+1

VHao ma rację; kontekst może zostać zmieniony podczas pisania większej liczby argumentów, co skutkuje nieoczekiwanym wyjściem, które imho można dobrze opisać jako niechronione wątkami – MacHala

2

Wszystko, czego potrzebujesz, to zsynchronizować wątki. Można to łatwo zrobić, korzystając z funkcji join() w bibliotece wątków.

można zrobić coś takiego

class myThread(threading.Thread): 
    def __init__(self, threadID, name): 
     threading.Thread.__init__(self) 
     self.threadID = threadID 
     self.name = name 

    def run(self): 
     currentThreadname = threading.currentThread() 
     print "running in ", currentThreadname 

thread = myThread(1,"mythrd") 
t1 = thread.start() 
t1.join() 
t2 = thread.run() 
t2.join() 

Można również użyć semafora i zablokować lepszych powodów. Zobacz dokumentację, aby uzyskać więcej szczegółów.

2

Prawdopodobnie nie rozumiesz, jak działają wątki. Przeczytaj uważnie this.

Sugeruję, aby użyć ThreadPoolExecutor z biblioteki futures.

Powiązane problemy