Was ist die Verwendung von join() beim Threading?

Lesezeit: 10 Minuten

Benutzeravatar von user192362127
Benutzer192362127

Ich habe das Python-Threading studiert und bin darauf gestoßen join().

Der Autor sagte, dass ich verwenden muss, wenn sich der Thread im Daemon-Modus befindet join() damit der Thread sich selbst beenden kann, bevor der Hauptthread beendet wird.

aber ich habe ihn auch benutzen gesehen t.join() wenngleich t war nicht daemon

Beispielcode ist dieser

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()

Ich weiß nicht, was nützt t.join() da es kein Daemon ist und ich keine Änderung sehen kann, selbst wenn ich es entferne

  • +1 für den Titel. ‘Join’ scheint speziell darauf ausgelegt zu sein, schlechte Leistung (durch kontinuierliches Erstellen/Beenden/Zerstören von Threads), GUI-Sperren (Warten in Event-Handlern) und Fehler beim Herunterfahren von Apps (Warten auf die Beendigung von nicht unterbrechbaren Threads) zu fördern. Hinweis – nicht nur Python, dies ist ein sprachübergreifendes Anti-Pattern.

    – Martin Jakob

    26. Februar 2013 um 11:00 Uhr


  • Viele Antworten geben nur an, was .join() tut. Aber ich denke, die eigentliche Frage ist, was der Sinn von .join() ist, wenn es den gleichen Effekt zu haben scheint wie das Ausführen Ihres Skripts ohne Threading.

    – Josch

    10. Dezember 2020 um 12:50 Uhr

Benutzeravatar von Don Question
Don Frage

Eine etwas ungeschickte ASCII-Kunst, um den Mechanismus zu demonstrieren: Die join() wird vermutlich vom Haupt-Thread aufgerufen. Es könnte auch von einem anderen Thread aufgerufen werden, würde aber das Diagramm unnötig verkomplizieren.

join-calling sollte in der Spur des Haupt-Threads platziert werden, aber um die Thread-Beziehung auszudrücken und es so einfach wie möglich zu halten, habe ich mich dafür entschieden, es stattdessen im untergeordneten Thread zu platzieren.

without join:
+---+---+------------------                     main-thread
    |   |
    |   +...........                            child-thread(short)
    +..................................         child-thread(long)

with join
+---+---+------------------***********+###      main-thread
    |   |                             |
    |   +...........join()            |         child-thread(short)
    +......................join()......         child-thread(long)

with join and daemon thread
+-+--+---+------------------***********+###     parent-thread
  |  |   |                             |
  |  |   +...........join()            |        child-thread(short)
  |  +......................join()......        child-thread(long)
  +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,     child-thread(long + daemonized)

'-' main-thread/parent-thread/main-program execution
'.' child-thread execution
'#' optional parent-thread execution after join()-blocked parent-thread could 
    continue
'*' main-thread 'sleeping' in join-method, waiting for child-thread to finish
',' daemonized thread - 'ignores' lifetime of other threads;
    terminates when main-programs exits; is normally meant for 
    join-independent tasks

Der Grund, warum Sie keine Änderungen sehen, ist, dass Ihr Hauptthread nichts nach Ihrem tut join. Du könntest sagen join ist (nur) für den Ausführungsablauf des Haupt-Threads relevant.

Wenn Sie beispielsweise eine Reihe von Seiten gleichzeitig herunterladen möchten, um sie zu einer einzigen großen Seite zu verketten, können Sie gleichzeitige Downloads mithilfe von Threads starten, müssen aber warten, bis die letzte Seite/der letzte Thread fertig ist, bevor Sie mit dem Zusammenstellen einer einzelnen Seite beginnen von vielen. Das ist, wenn Sie verwenden join().

  • Bitte bestätigen Sie, dass ein daemonisierter Thread beigetreten werden kann (), ohne die Programmausführung zu blockieren?

    – Aviator45003

    3. März 2015 um 8:52 Uhr

  • @ Aviator45003: Ja, indem Sie das Timeout-Argument wie folgt verwenden: demon_thread.join(0.0), join() blockiert standardmäßig ohne Rücksicht auf das daemonisierte Attribut. Aber der Beitritt zu einem dämonisierten Thread führt höchstwahrscheinlich zu einer ganzen Dose Ärger! Ich überlege jetzt, die zu entfernen join() Rufen Sie mein kleines Diagramm für den Daemon-Thread auf …

    – Keine Frage

    3. März 2015 um 17:15 Uhr


  • @DonQuestion Also, wenn wir uns auf den Weg machen daemon=True brauchen wir das nicht join() wenn wir das brauchen join() am Ende des Codes?

    – Benyamin Jafari – aGn

    22. Januar 2019 um 8:32 Uhr


  • @BenyaminJafari: Ja. Wenn nicht, dann würde der Main-Thread (=Programm) beendet werden, wenn nur noch der Daemon-Thread übrig bleibt. Aber die Natur eines (Python-)Daemon-Threads ist, dass es dem Haupt-Thread egal ist, ob diese Hintergrundaufgabe noch läuft. Ich werde darüber nachdenken, wie ich das in meiner Antwort näher erläutern kann, um dieses Problem zu klären. Vielen Dank für Ihren Kommentar!

    – Keine Frage

    18. März 2019 um 21:25 Uhr


  • Im ersten Fall, wenn die main thread endet, wird das Programm beendet, ohne zu lassen child-thread(long) sich selbst beenden (dh child-thread(long) ist noch nicht ganz fertig)?

    – Himmelsbaum

    21. Oktober 2019 um 20:51 Uhr


Benutzeravatar von dmg
dmg

Direkt von der Dokumente

beitreten([timeout]) Warten Sie, bis der Thread beendet ist. Dadurch wird der aufrufende Thread blockiert, bis der Thread, dessen Methode join() aufgerufen wird, beendet wird – entweder normal oder durch eine nicht behandelte Ausnahme – oder bis das optionale Timeout eintritt.

Dies bedeutet, dass der Hauptthread spawnt t und dwartet auf t zu beenden, bis es fertig ist.

Abhängig von der Logik Ihres Programms möchten Sie möglicherweise warten, bis ein Thread beendet ist, bevor Ihr Hauptthread fortgesetzt wird.

Auch aus der Doku:

Ein Thread kann als „Daemon-Thread“ gekennzeichnet werden. Die Bedeutung dieses Flags besteht darin, dass das gesamte Python-Programm beendet wird, wenn nur noch Daemon-Threads übrig sind.

Ein einfaches Beispiel, sagen wir, wir haben dies:

def non_daemon():
    time.sleep(5)
    print 'Test non-daemon'

t = threading.Thread(name="non-daemon", target=non_daemon)

t.start()

Was endet mit:

print 'Test one'
t.join()
print 'Test two'

Dies wird ausgeben:

Test one
Test non-daemon
Test two

Hier wartet der Master-Thread explizit auf die t Thread zu beenden, bis er aufruft print das zweite Mal.

Alternativ, wenn wir dies hätten:

print 'Test one'
print 'Test two'
t.join()

Wir erhalten diese Ausgabe:

Test one
Test two
Test non-daemon

Hier erledigen wir unsere Arbeit im Hauptthread und dann warten wir auf die t Faden zum Abschluss. In diesem Fall entfernen wir möglicherweise sogar die explizite Verknüpfung t.join() und das Programm wird implizit warten t beenden.

  • Können Sie etwas an meinem Code ändern, damit ich den Unterschied von sehen kann t.join(). durch Hinzufügen von etwas Schlaf oder etwas anderem. Im Moment kann ich jede Änderung im Programm sehen, auch wenn ich es benutze oder nicht. aber für damon kann ich seinen Ausgang sehen, wenn ich es benutze d.join() was ich nicht sehe, wenn ich d.join() nicht verwende

    – Benutzer192362127

    26. Februar 2013 um 9:46 Uhr


Benutzeravatar von Kiki Jewell
Kiki Schmuck

Danke für diesen Thread – er hat mir auch sehr geholfen.

Ich habe heute etwas über .join() gelernt.

Diese Threads laufen parallel:

d.start()
t.start()
d.join()
t.join()

und diese laufen nacheinander (nicht das, was ich wollte):

d.start()
d.join()
t.start()
t.join()

Insbesondere habe ich versucht, clever und ordentlich zu sein:

class Kiki(threading.Thread):
    def __init__(self, time):
        super(Kiki, self).__init__()
        self.time = time
        self.start()
        self.join()

Das funktioniert! Aber es läuft sequentiell. Ich kann self.start() in __ init __ einfügen, aber nicht self.join(). Das muss getan werden nach Jeder Thread wurde gestartet.

join() bewirkt, dass der Hauptthread auf das Ende Ihres Threads wartet. Ansonsten läuft dein Thread von alleine.

Man kann sich join() also als “Halten” für den Haupt-Thread vorstellen – es entzieht Ihrem Thread gewissermaßen die Threads und wird sequentiell im Haupt-Thread ausgeführt, bevor der Haupt-Thread fortfahren kann. Es stellt sicher, dass Ihr Thread abgeschlossen ist, bevor der Hauptthread voranschreitet. Beachten Sie, dass es in Ordnung ist, wenn Ihr Thread bereits fertig ist, bevor Sie join() aufrufen – der Haupt-Thread wird einfach sofort freigegeben, wenn join() aufgerufen wird.

Tatsächlich fällt mir gerade ein, dass der Haupt-Thread bei d.join() wartet, bis Thread d beendet ist, bevor er zu t.join() weitergeht.

Um ganz klar zu sein, betrachten Sie diesen Code:

import threading
import time

class Kiki(threading.Thread):
    def __init__(self, time):
        super(Kiki, self).__init__()
        self.time = time
        self.start()

    def run(self):
        print self.time, " seconds start!"
        for i in range(0,self.time):
            time.sleep(1)
            print "1 sec of ", self.time
        print self.time, " seconds finished!"


t1 = Kiki(3)
t2 = Kiki(2)
t3 = Kiki(1)
t1.join()
print "t1.join() finished"
t2.join()
print "t2.join() finished"
t3.join()
print "t3.join() finished"

Es erzeugt diese Ausgabe (beachten Sie, wie die Druckanweisungen ineinander eingefädelt sind.)

$ python test_thread.py
32   seconds start! seconds start!1

 seconds start!
1 sec of  1
 1 sec of 1  seconds finished!
 21 sec of
3
1 sec of  3
1 sec of  2
2  seconds finished!
1 sec of  3
3  seconds finished!
t1.join() finished
t2.join() finished
t3.join() finished
$ 

t1.join() hält den Hauptthread auf. Alle drei Threads werden abgeschlossen, bevor t1.join() beendet wird, und der Hauptthread fährt fort, um print auszuführen, dann t2.join(), dann print, dann t3.join(), dann print.

Korrekturen erwünscht. Ich bin auch neu im Threading.

(Hinweis: Falls Sie interessiert sind, ich schreibe Code für einen DrinkBot, und ich brauche Threading, um die Zutatenpumpen gleichzeitig und nicht nacheinander laufen zu lassen – weniger Zeit zum Warten auf jedes Getränk.)

  • Hey, ich bin auch neu im Python-Threading und verwirrt über den Haupt-Thread, ist der erste Thread der Haupt-Thread, wenn nicht, bitte führen Sie mich?

    – Rohit Khatri

    11. August 2016 um 6:14 Uhr

  • Der Hauptfaden ist das Programm selbst. Jeder der Threads wird von dort aus gegabelt. Sie werden dann wieder zusammengeführt – denn beim Befehl join() wartet das Programm, bis der Thread beendet ist, bevor es weiter ausgeführt wird.

    – Kiki Juwel

    3. Januar 2017 um 5:16 Uhr

  • Ich denke, die große Frage, warum Sie den Hauptthread aufhalten wollen, wenn der ganze Sinn des Threadings darin besteht, parallel zu laufen. Ich denke, die Antwort auf join () ist, dass Sie vielleicht Teile Ihres Programms parallel ausführen möchten, aber möglicherweise einen Teil Ihres Hauptthreads erreichen, der das Ergebnis Ihres Unterthreads benötigt, bevor Sie fortfahren?

    – Josch

    1. Oktober 2021 um 11:58 Uhr

Ketouems Benutzeravatar
Ketouem

Die Methode join()

blockiert den aufrufenden Thread, bis der Thread, dessen Methode join() aufgerufen wird, beendet wird.

Quelle : http://docs.python.org/2/library/threading.html

Benutzeravatar von Mohideen bin Mohammed
Mohidin bin Mohammed

Mit Join – Interpreter wartet, bis Ihr Prozess kommt abgeschlossen oder beendet

>>> from threading import Thread
>>> import time
>>> def sam():
...   print 'started'
...   time.sleep(10)
...   print 'waiting for 10sec'
... 
>>> t = Thread(target=sam)
>>> t.start()
started

>>> t.join() # with join interpreter will wait until your process get completed or terminated
done?   # this line printed after thread execution stopped i.e after 10sec
waiting for 10sec
>>> done?

ohne Join – Interpreter wartet nicht, bis der Prozess kommt beendet,

>>> t = Thread(target=sam)
>>> t.start()
started
>>> print 'yes done' #without join interpreter wont wait until process get terminated
yes done
>>> waiting for 10sec

Benutzeravatar von Shishir Nanoty
Shishir Nanoty

In Python 3.x wird join() verwendet, um einen Thread mit dem Hauptthread zu verbinden, dh wenn join() für einen bestimmten Thread verwendet wird, stoppt der Hauptthread die Ausführung, bis die Ausführung des verbundenen Threads abgeschlossen ist.

#1 - Without Join():
import threading
import time
def loiter():
    print('You are loitering!')
    time.sleep(5)
    print('You are not loitering anymore!')

t1 = threading.Thread(target = loiter)
t1.start()
print('Hey, I do not want to loiter!')
'''
Output without join()--> 
You are loitering!
Hey, I do not want to loiter!
You are not loitering anymore! #After 5 seconds --> This statement will be printed

'''
#2 - With Join():
import threading
import time
def loiter():
    print('You are loitering!')
    time.sleep(5)
    print('You are not loitering anymore!')

t1 = threading.Thread(target = loiter)
t1.start()
t1.join()
print('Hey, I do not want to loiter!')

'''
Output with join() -->
You are loitering!
You are not loitering anymore! #After 5 seconds --> This statement will be printed
Hey, I do not want to loiter! 

'''

Dieses Beispiel demonstriert die .join() Aktion:

import threading
import time

def threaded_worker():
    for r in range(10):
        print('Other: ', r)
        time.sleep(2)

thread_ = threading.Timer(1, threaded_worker)
thread_.daemon = True  # If the main thread is killed, this thread will be killed as well. 
thread_.start()

flag = True

for i in range(10):
    print('Main: ', i)
    time.sleep(2)
    if flag and i > 4:
        print(
            '''
            Threaded_worker() joined to the main thread. 
            Now we have a sequential behavior instead of concurrency.
            ''')
        thread_.join()
        flag = False

Aus:

Main:  0
Other:  0
Main:  1
Other:  1
Main:  2
Other:  2
Main:  3
Other:  3
Main:  4
Other:  4
Main:  5
Other:  5

            Threaded_worker() joined to the main thread. 
            Now we have a sequential behavior instead of concurrency.
            
Other:  6
Other:  7
Other:  8
Other:  9
Main:  6
Main:  7
Main:  8
Main:  9

1436380cookie-checkWas ist die Verwendung von join() beim Threading?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy