Al fin luego de tanto luchar ya hallamos la contestación de este apuro que muchos lectores de este sitio presentan. Si tienes alguna información que aportar puedes aportar tu conocimiento.
Solución:
Un arte ascii algo torpe para demostrar el mecanismo: join()
es presumiblemente llamado por el subproceso principal. También podría ser llamado por otro hilo, pero complicaría innecesariamente el diagrama.
join
-calling debe colocarse en la pista del subproceso principal, pero para expresar la relación del subproceso y mantenerlo lo más simple posible, elijo colocarlo en el subproceso secundario.
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
Entonces, la razón por la que no ve ningún cambio es porque su hilo principal no hace nada después de su join
. Tu puedes decir join
es (solo) relevante para el flujo de ejecución del hilo principal.
Si, por ejemplo, desea descargar simultáneamente un montón de páginas para concatenarlas en una sola página grande, puede iniciar descargas simultáneas utilizando hilos, pero debe esperar hasta que finalice la última página / hilo antes de comenzar a ensamblar una sola página. Fuera de muchos. Ahí es cuando usas join()
.
Directamente de los documentos
entrar([timeout]) Espere hasta que termine el hilo. Esto bloquea el subproceso que realiza la llamada hasta que el subproceso cuyo método join () se llama termina, ya sea normalmente o mediante una excepción no controlada, o hasta que se agota el tiempo de espera opcional.
Esto significa que el hilo principal que genera t
y d
, espera t
para terminar hasta que termine.
Dependiendo de la lógica que emplee su programa, es posible que desee esperar hasta que finalice un hilo antes de que continúe su hilo principal.
También de los documentos:
Un hilo se puede marcar como un “hilo demonio”. El significado de esta bandera es que todo el programa Python se cierra cuando solo quedan subprocesos del demonio.
Un ejemplo simple, digamos que tenemos esto:
def non_daemon():
time.sleep(5)
print 'Test non-daemon'
t = threading.Thread(name='non-daemon', target=non_daemon)
t.start()
Que termina con:
print 'Test one'
t.join()
print 'Test two'
Esto dará como resultado:
Test one
Test non-daemon
Test two
Aquí el hilo maestro espera explícitamente el t
hilo para terminar hasta que llame print
la segunda vez.
Alternativamente, si tuviéramos esto:
print 'Test one'
print 'Test two'
t.join()
Obtendremos esta salida:
Test one
Test two
Test non-daemon
Aquí hacemos nuestro trabajo en el hilo principal y luego esperamos el t
hilo para terminar. En este caso, incluso podríamos eliminar la unión explícita t.join()
y el programa esperará implícitamente t
para terminar.
Gracias por este hilo, también me ayudó mucho.
Aprendí algo sobre .join () hoy.
Estos subprocesos se ejecutan en paralelo:
d.start()
t.start()
d.join()
t.join()
y estos se ejecutan secuencialmente (no es lo que quería):
d.start()
d.join()
t.start()
t.join()
En particular, estaba tratando de ser inteligente y ordenado:
class Kiki(threading.Thread):
def __init__(self, time):
super(Kiki, self).__init__()
self.time = time
self.start()
self.join()
¡Esto funciona! Pero se ejecuta de forma secuencial. Puedo poner self.start () en __ init __, pero no self.join (). Eso tiene que ser hecho después se ha iniciado cada hilo.
join () es lo que hace que el hilo principal espere a que termine su hilo. De lo contrario, su hilo se ejecuta por sí solo.
Entonces, una forma de pensar en join () como una “retención” en el hilo principal – en cierto modo deshilacha su hilo y se ejecuta secuencialmente en el hilo principal, antes de que el hilo principal pueda continuar. Asegura que su hilo esté completo antes de que el hilo principal avance. Tenga en cuenta que esto significa que está bien si su hilo ya está terminado antes de llamar a join (); el hilo principal simplemente se libera inmediatamente cuando se llama a join ().
De hecho, se me acaba de ocurrir que el hilo principal espera en d.join () hasta que el hilo d termine antes de pasar a t.join ().
De hecho, para ser muy claro, considere este código:
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"
Produce esta salida (observe cómo las declaraciones de impresión se entrelazan entre sí).
$ 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
$
El t1.join () está sosteniendo el hilo principal. Los tres subprocesos se completan antes de que finalice t1.join () y el subproceso principal se mueve para ejecutar la impresión, luego t2.join () luego imprime luego t3.join () y luego imprime.
Las correcciones son bienvenidas. También soy nuevo en enhebrar.
(Nota: en caso de que esté interesado, estoy escribiendo código para un DrinkBot, y necesito enhebrar para ejecutar las bombas de ingredientes al mismo tiempo en lugar de secuencialmente, menos tiempo para esperar por cada bebida).
Eres capaz de añadir valor a nuestra información colaborando tu experiencia en los informes.