web-dev-qa-db-de.com

was ist die Verwendung von join () in Python-Threading

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

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

aber ich habe ihn auch mit t.join() gesehen, obwohl t nicht daemon war

beispielcode ist dies

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 von t.join() verwendet wird, da es kein Daemon ist und ich kann keine Änderung sehen, selbst wenn ich es entferne

130
user192362127

Eine etwas ungeschickte Ascii-Art, 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 jedoch das Diagramm unnötig komplizieren.

join- Aufruf sollte in der Spur des Haupt-Threads platziert werden. Um die Thread-Relation jedoch auszudrücken und so einfach wie möglich zu halten, wähle ich sie stattdessen im Child-Thread.

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 Main-Thread nach Ihrer join..__ nichts tut. Sie könnten sagen, dass join (nur) für den Ausführungsablauf des Main-Threads relevant ist.

Wenn Sie beispielsweise mehrere Seiten gleichzeitig herunterladen möchten, um sie zu einer großen Seite zu verketten, starten Sie möglicherweise gleichzeitige Downloads mit Threads. Sie müssen jedoch warten, bis die letzte Seite/der letzte Thread beendet ist, bevor Sie mit dem Zusammenfügen einer einzelnen Seite beginnen von vielen. Dann verwenden Sie join().

206
Don Question

Direkt aus den docs

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

Dies bedeutet, dass der Haupt-Thread, der t und d erzeugt, auf t wartet, bis er beendet ist.

Abhängig von der von Ihrem Programm verwendeten Logik möchten Sie möglicherweise warten, bis ein Thread beendet ist, bevor der Haupt-Thread fortgesetzt wird.

Auch aus den Dokumenten:

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

Ein einfaches Beispiel sagen wir haben folgendes:

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 ausgegeben:

Test one
Test non-daemon
Test two

Hier wartet der Master-Thread explizit auf den Abschluss des t-Threads, bis er print zum zweiten Mal aufruft.

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 machen wir unsere Arbeit im Hauptthread und warten dann, bis der t-Thread beendet ist. In diesem Fall können wir sogar den expliziten Beitritt t.join() entfernen, und das Programm wartet implizit, bis t abgeschlossen ist.

52
dmg

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 ab (nicht was ich wollte):

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

Insbesondere habe ich versucht, klug und aufgeräumt 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 nacheinander. Ich kann das self.start () in __ init __ einfügen, aber nicht das self.join (). Das muss gemacht werden nachdem jeder Thread gestartet wurde.

mit join () wartet der Haupt-Thread, bis der Thread beendet ist. Andernfalls läuft Ihr Thread von alleine.

Eine Möglichkeit, join () als ein "Halten" im Haupt-Thread zu betrachten - es dekodiert Ihren Thread und führt ihn sequentiell im Haupt-Thread aus, bevor der Haupt-Thread fortfahren kann. Es stellt sicher, dass Ihr Thread abgeschlossen ist, bevor sich der Haupt-Thread vorwärts bewegt. Beachten Sie, dass dies in Ordnung ist, wenn der Thread bereits fertig ist, bevor Sie join () aufrufen. Der Haupt-Thread wird beim Aufruf von join () einfach sofort freigegeben.

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

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 gefädelt werden.)

$ 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 Haupt-Thread hoch. Alle drei Threads sind abgeschlossen, bevor t1.join () beendet ist. Der Haupt-Thread wird dann weiter ausgeführt, um den Druck auszuführen, dann t2.join () und dann t3.join () und dann zu drucken.

Korrekturen sind willkommen. Ich bin auch neu im Threading.

(Hinweis: Wenn Sie interessiert sind, schreibe ich Code für einen DrinkBot und ich muss ein Threading ausführen, um die Komponentenpumpen gleichzeitig und nicht nacheinander zu betreiben - weniger Zeit, um auf jedes Getränk zu warten.)

28
Kiki Jewell

Die Methode join ()

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

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

13
Ketouem

Wenn Sie join(t) für sowohl Nicht-Daemon-Thread als auch Daemon-Thread festlegen, sollte der Haupt-Thread (oder der Hauptprozess) t Sekunden warten, bevor er seinen eigenen Prozess weiterarbeiten kann. Während der Wartezeit von t Sekunden sollten beide untergeordneten Threads das tun, was sie können, z. B. den Ausdruck von Text. Nach den t Sekunden, wenn der Nicht-Daemon-Thread seinen Job immer noch nicht beendet hat, kann er ihn immer noch beenden, nachdem der Hauptprozess seinen Job abgeschlossen hat. Bei einem Daemon-Thread hat er jedoch sein Opportunity-Fenster verpasst. Es wird jedoch schließlich sterben, nachdem das Python-Programm beendet wurde. Bitte korrigieren Sie mich, wenn etwas nicht stimmt.

1
user1342336

Einfach verstehen,

with join - Der Interpreter wartet, bis Ihr Prozess erledigt 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 - der Interpreter wartet nicht, bis der Prozess beendet wird ,

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

Dieses Beispiel zeigt die Aktion .join():

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 kills, this thread will be killed too. 
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
0
Benyamin Jafari

In python 3.x wird join () verwendet, um einen Thread mit dem Haupt-Thread zu verbinden, d. H. Wenn join () für einen bestimmten Thread verwendet wird, stoppt der Haupt-Thread die Ausführung, bis die Ausführung des verbundenen Thread 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! 

'''
0
Shishir Nanoty