Studiowałem wątki w pythonie i natknąłem się join()
.
Autor powiedział, że jeśli wątek jest w trybie demona, muszę go użyć join()
, aby wątek mógł zakończyć się przed zakończeniem głównego wątku.
ale widziałem go również używającego, t.join()
chociaż t
tak nie byłodaemon
przykładowy kod to
import threading
import time
import logging
logging.basicConfig(level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
def daemon():
logging.debug('Starting')
time.sleep(2)
logging.debug('Exiting')
d = threading.Thread(name='daemon', target=daemon)
d.setDaemon(True)
def non_daemon():
logging.debug('Starting')
logging.debug('Exiting')
t = threading.Thread(name='non-daemon', target=non_daemon)
d.start()
t.start()
d.join()
t.join()
nie wiem, co to jest, t.join()
ponieważ nie jest demonem, i nie widzę żadnych zmian, nawet jeśli go usunę
python
multithreading
python-multithreading
użytkownik192362127
źródło
źródło
Odpowiedzi:
Trochę niezdarna ascii-art, aby zademonstrować mechanizm:
join()
Przypuszczalnie nazywany jest przez główny wątek. Może być również wywołany przez inny wątek, ale niepotrzebnie skomplikowałby schemat.join
-calling powinien być umieszczony na ścieżce głównego wątku, ale aby wyrazić relację wątku i uprościć go tak prosto, jak to możliwe, wybieram umieszczenie go w wątku potomnym.Dlatego powodem, dla którego nie widzisz żadnych zmian, jest to, że Twój główny wątek nic nie robi po twoim
join
. Można powiedzieć, żejoin
jest (tylko) istotny dla przepływu wykonania głównego wątku.Jeśli na przykład chcesz jednocześnie pobrać kilka stron, aby połączyć je w jedną dużą stronę, możesz rozpocząć jednoczesne pobieranie za pomocą wątków, ale musisz poczekać, aż ostatnia strona / wątek zostanie zakończony, zanim zaczniesz składać pojedynczą stronę z wielu. Właśnie wtedy używasz
join()
.źródło
demon_thread.join(0.0)
,join()
to poprzez blokowanie bez względu na atrybut daemonized domyślnie. Ale dołączenie do demonizowanego wątku otwiera najprawdopodobniej całą kłopot! Zastanawiam się teraz nad usunięciemjoin()
wywołania z mojego małego diagramu dla wątku demona ...daemon=True
nie potrzebujemy,join()
jeśli potrzebujemyjoin()
na końcu kodu?main thread
zakończy, czy program zakończy się, nie pozwalając, bychild-thread(long)
sam się uruchomił (tzn.child-thread(long)
Nie jest całkowicie ukończony)?Prosto z dokumentów
Oznacza to, że główny wątek, który się odradza
t
id
czeka nat
zakończenie, dopóki się nie skończy.W zależności od logiki używanej przez program, możesz poczekać, aż wątek się zakończy, zanim główny wątek będzie kontynuowany.
Również z dokumentów:
Prosty przykład, powiedzmy, że mamy to:
Który kończy się na:
Spowoduje to wygenerowanie:
Tutaj wątek główny jawnie czeka na zakończenie
t
wątku, aż zadzwoniprint
po raz drugi.Alternatywnie, jeśli mielibyśmy to:
Otrzymamy ten wynik:
Tutaj wykonujemy naszą pracę w głównym wątku, a następnie czekamy na zakończenie
t
wątku. W takim przypadku możemy nawet usunąć jawne połączenie,t.join()
a program domyślnie poczeka nat
zakończenie.źródło
t.join()
. przez dodanie snu lub czegoś innego. w tej chwili mogę zobaczyć dowolny program w programie, nawet jeśli go używam lub nie. ale dla damemona widzę jego wyjście, jeśli korzystam z tego,d.join()
którego nie widzę, gdy nie używam d.join ()Dzięki za ten wątek - bardzo mi też pomógł.
Nauczyłem się dziś czegoś o .join ().
Te wątki działają równolegle:
a te działają sekwencyjnie (nie to, co chciałem):
W szczególności starałem się sprytnie i uporządkować:
To działa! Ale działa sekwencyjnie. Mogę umieścić self.start () w __ init __, ale nie self.join (). Należy to zrobić po rozpoczęciu każdego wątku.
join () powoduje, że główny wątek czeka na zakończenie wątku. W przeciwnym razie wątek działa sam.
Tak więc jednym ze sposobów myślenia o złączeniu () jako „wstrzymaniu” głównego wątku - jest to rodzaj usuwania wątków z wątku i wykonywania sekwencyjnego w głównym wątku, zanim główny wątek będzie mógł kontynuować. Zapewnia, że Twój wątek jest kompletny, zanim główny wątek przejdzie do przodu. Zauważ, że oznacza to, że nic nie szkodzi, jeśli Twój wątek jest już zakończony przed wywołaniem funkcji join () - główny wątek jest po prostu zwalniany natychmiast po wywołaniu funkcji join ().
W rzeczywistości właśnie teraz przychodzi mi do głowy, że główny wątek czeka w d.join (), aż wątek d zakończy się, zanim przejdzie do t.join ().
W rzeczywistości, aby być bardzo jasnym, rozważ ten kod:
Tworzy to wyjście (zwróć uwagę, w jaki sposób instrukcje drukowania są ze sobą powiązane.)
T1.join () utrzymuje główny wątek. Wszystkie trzy wątki zakończą się przed zakończeniem t1.join (), a główny wątek przejdzie do wykonania drukowania, następnie t2.join (), następnie wydrukuj następnie t3.join (), a następnie wydrukuj.
Korekty mile widziane. Jestem również nowy w wątkach.
(Uwaga: jeśli jesteś zainteresowany, piszę kod dla DrinkBota i potrzebuję wątków, aby uruchomić pompy składników jednocześnie, a nie sekwencyjnie - mniej czasu na czekanie na każdego drinka.)
źródło
Metoda join ()
Źródło: http://docs.python.org/2/library/threading.html
źródło
t.join()
a program nadal czeka na to przed zakończeniem. nie widzę tu żadnego zastosowaniat.join()
w moim kodzieProste zrozumienie,
z dołączeniem - tłumacz będzie czekać na zakończenie lub zakończenie procesu
bez dołączenia - tłumacz nie będzie czekał na zakończenie procesu ,
źródło
Podczas wykonywania
join(t)
funkcji zarówno dla wątku nie-demonicznego, jak i wątku demonicznego, wątek główny (lub proces główny) powinien poczekaćt
kilka sekund, a następnie może przejść dalej do pracy nad własnym procesem. W ciągut
sekundy oczekiwania oba wątki podrzędne powinny zrobić to, co mogą, na przykład wydrukować tekst. Pot
kilku sekundach, jeśli wątek inny niż demon nadal nie ukończył zadania, i nadal może go ukończyć po zakończeniu procesu głównego, ale w przypadku wątku demona po prostu przegapił swoje okno możliwości. Jednak ostatecznie umrze po wyjściu z programu python. Popraw mnie, jeśli coś jest nie tak.źródło
W Pythonie 3.x join () służy do łączenia wątku z głównym wątkiem, tzn. Gdy joach () jest używany do określonego wątku, główny wątek przestanie działać do momentu zakończenia wykonywania połączonego wątku.
źródło
W tym przykładzie pokazano
.join()
działanie:Na zewnątrz:
źródło
Istnieje kilka powodów, dla których główny wątek (lub jakikolwiek inny wątek) dołącza do innych wątków
Wątek mógł utworzyć lub zatrzymać (zablokować) niektóre zasoby. Wątek łączący może być w stanie wyczyścić zasoby w jego imieniu
join () to naturalne blokujące wywołanie dla wątku wywołującego łączenie, które będzie kontynuowane po zakończeniu wywoływanego wątku.
Jeśli program w języku Python nie dołącza do innych wątków, interpreter języka Python nadal dołącza do niego wątki niebędące demonami.
źródło
„Po co korzystać z join ()?” mówisz. Naprawdę jest to ta sama odpowiedź, co „po co zamykanie plików, skoro Python i system operacyjny zamkną mój plik dla mnie, gdy mój program zakończy pracę?”.
To po prostu kwestia dobrego programowania. Powinieneś dołączyć () do swoich wątków w punkcie kodu, w którym wątek nie powinien być uruchomiony, albo dlatego, że musisz upewnić się, że wątek nie działa, aby zakłócać twój własny kod, lub że chcesz zachowywać się poprawnie w większy system.
Możesz powiedzieć „Nie chcę, aby mój kod opóźniał udzielenie odpowiedzi” tylko ze względu na dodatkowy czas, którego może wymagać funkcja join (). Może to być całkowicie poprawne w niektórych scenariuszach, ale musisz teraz wziąć pod uwagę, że twój kod „pozostawia cruft w pobliżu dla Pythona i systemu operacyjnego do wyczyszczenia”. Jeśli robisz to ze względu na wydajność, gorąco zachęcam do udokumentowania tego zachowania. Jest to szczególnie prawdziwe, jeśli budujesz bibliotekę / pakiet, z którego inni powinni korzystać.
Nie ma powodu, aby nie dołączać (), oprócz powodów wydajności, i argumentowałbym, że twój kod nie musi działać tak dobrze.
źródło
join()
.