Estaba estudiando el subproceso de pitón y me encontré join()
.
El autor dijo que si el hilo está en modo demonio, entonces necesito usarlo join()
para que el hilo pueda terminar antes de que termine el hilo principal.
pero también lo he visto usar t.join()
aunque t
no eradaemon
código de ejemplo es este
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()
No sé de qué sirve, t.join()
ya que no es demonio y no puedo ver ningún cambio, incluso si lo elimino
python
multithreading
python-multithreading
usuario192362127
fuente
fuente
Respuestas:
Un ascii-arte algo torpe para demostrar el mecanismo:
join()
el hilo principal presumiblemente lo llama. También podría ser llamado por otro hilo, pero complicaría innecesariamente el diagrama.join
-call debe colocarse en la pista del hilo principal, pero para expresar la relación de hilo y mantenerlo lo más simple posible, elijo colocarlo en el hilo secundario.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
. Se podría decir quejoin
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 usando hilos, pero debe esperar hasta que la última página / hilo termine antes de comenzar a ensamblar una sola página Fuera de muchos. Ahí es cuando lo usas
join()
.fuente
demon_thread.join(0.0)
,join()
es mediante el bloqueo sin tener en cuenta el atributo endemoniada por defecto. ¡Pero unirse a un hilo demonizado abre muy probablemente toda una lata de problemas! Ahora estoy considerando eliminar lajoin()
llamada en mi pequeño diagrama para el hilo del demonio ...daemon=True
¿no necesitamosjoin()
si necesitamos aljoin()
final del código?main thread
finalice, ¿finalizará el programa sin dejar quechild-thread(long)
termine de ejecutarse (child-thread(long)
es decir, no está completamente terminado)?Directo de los documentos
Esto significa que el hilo principal que genera
t
yd
espera at
que termine hasta que termine.Dependiendo de la lógica que emplee su programa, es posible que desee esperar hasta que un hilo termine antes de que su hilo principal continúe.
También de los documentos:
Un ejemplo simple, digamos que tenemos esto:
Que termina con:
Esto generará:
Aquí el hilo maestro espera explícitamente
t
a que termine el hilo hasta que llame porprint
segunda vez.Alternativamente, si tuviéramos esto:
Obtendremos esta salida:
Aquí hacemos nuestro trabajo en el hilo principal y luego esperamos que el
t
hilo termine. En este caso, incluso podríamos eliminar la unión explícitat.join()
y el programa esperará implícitamente at
que termine.fuente
t.join()
? agregando algo de sueño o algo más. en este momento puedo ver cualquier cambio en el programa, incluso si lo uso o no. pero para damemon puedo ver su salida si yo usod.join()
, que no veo cuando yo no uso d.join ()Gracias por este hilo, también me ayudó mucho.
Hoy aprendí algo sobre .join ().
Estos hilos se ejecutan en paralelo:
y estos se ejecutan secuencialmente (no es lo que quería):
En particular, estaba tratando de ser inteligente y ordenado:
¡Esto funciona! Pero se ejecuta secuencialmente. Puedo poner self.start () en __ init __, pero no self.join (). Eso debe hacerse después de que se haya 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.
Por lo tanto, una forma de pensar en join () como una "retención" en el hilo principal: deshilacha el 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, justo ahora se me ocurre que el hilo principal espera en d.join () hasta que el hilo d finalice antes de pasar a t.join ().
De hecho, para ser muy claro, considere este código:
Produce esta salida (tenga en cuenta cómo se enhebran las declaraciones de impresión entre sí).
El t1.join () está sosteniendo el hilo principal. Los tres subprocesos se completan antes de que t1.join () termine y el subproceso principal se mueve para ejecutar la impresión, luego t2.join () luego imprime y luego t3.join () luego imprime.
Correcciones de bienvenida. También soy nuevo en el enhebrado.
(Nota: en caso de que le interese, estoy escribiendo un código para un DrinkBot, y necesito enhebrar para ejecutar las bombas de ingredientes de forma simultánea en lugar de secuencial, menos tiempo para esperar cada bebida).
fuente
El método join ()
Fuente: http://docs.python.org/2/library/threading.html
fuente
t.join()
y el programa todavía lo espera antes de la finalización. No veo ningún usot.join()
aquí en mi códigoSimple comprensión,
con join: el intérprete esperará hasta que su proceso se complete o finalice
sin unirse: el intérprete no esperará hasta que finalice el proceso ,
fuente
Al realizar la
join(t)
función tanto para el hilo que no es el demonio como para el hilo del demonio, el hilo principal (o proceso principal) debe esperart
segundos, luego puede ir más allá para trabajar en su propio proceso. Durante lost
segundos de espera, ambos hilos secundarios deben hacer lo que pueden hacer, como imprimir un texto. Después de lost
segundos, si el hilo que no es de daemon todavía no terminó su trabajo, y todavía puede terminarlo después de que el proceso principal termine su trabajo, pero para el hilo de daemon, simplemente perdió su ventana de oportunidad. Sin embargo, eventualmente morirá después de que el programa python salga. Por favor corrígeme si hay algo mal.fuente
En python 3.x join () se usa para unir un hilo con el hilo principal, es decir, cuando join () se usa para un hilo particular, el hilo principal dejará de ejecutarse hasta que se complete la ejecución del hilo unido.
fuente
Este ejemplo demuestra la
.join()
acción:Fuera:
fuente
Hay algunas razones para que el hilo principal (o cualquier otro hilo) se una a otros hilos
Un hilo puede haber creado o retenido (bloqueado) algunos recursos. El hilo de llamada conjunta puede borrar los recursos en su nombre
join () es una llamada de bloqueo natural para que el hilo de llamada de unión continúe después de que el hilo llamado haya terminado.
Si un programa de Python no se une a otros subprocesos, el intérprete de Python aún se unirá a subprocesos que no sean demonios en su nombre.
fuente
"¿De qué sirve usar join ()?" tu dices. Realmente, es la misma respuesta que "¿de qué sirve cerrar archivos, ya que Python y el sistema operativo cerrarán mi archivo cuando salga mi programa?".
Es simplemente una cuestión de buena programación. Debe unir () sus hilos en el punto del código que el hilo no debe debería ejecutarse, ya sea porque debe asegurarse de que el hilo no se esté ejecutando para interferir con su propio código, o que desea comportarse correctamente en un sistema más grande
Puede decir "No quiero que mi código demore en dar una respuesta" solo por el tiempo adicional que puede requerir la unión (). Esto puede ser perfectamente válido en algunos escenarios, pero ahora debe tener en cuenta que su código está "dejando un rumbo para que Python y el sistema operativo se limpien". Si hace esto por razones de rendimiento, le recomiendo que documente ese comportamiento. Esto es especialmente cierto si está creando una biblioteca / paquete que se espera que otros utilicen.
No hay ninguna razón para no unirse (), aparte de las razones de rendimiento, y diría que su código no necesita funcionar tan bien.
fuente
join()
.