Eu estava estudando a segmentação de python e me deparei join()
.
O autor disse que, se o encadeamento estiver no modo daemon, preciso usar join()
para que o encadeamento possa terminar antes que o encadeamento principal seja encerrado.
mas eu também o vi usando t.join()
mesmo que t
não fossedaemon
código de exemplo é 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()
não sei de que serve, t.join()
pois não é daemon e não consigo ver nenhuma alteração, mesmo que eu o remova
python
multithreading
python-multithreading
user192362127
fonte
fonte
Respostas:
Uma arte um tanto desajeitada para demonstrar o mecanismo:
join()
presumivelmente é chamado pelo thread principal. Também poderia ser chamado por outro thread, mas complicaria desnecessariamente o diagrama.join
-calling deve ser colocado na trilha do thread principal, mas para expressar a relação do thread e mantê-lo o mais simples possível, eu escolho colocá-lo no thread filho.Portanto, o motivo pelo qual você não vê nenhuma alteração é porque o thread principal não faz nada depois do seu
join
. Você poderia dizer quejoin
é (apenas) relevante para o fluxo de execução do thread principal.Se, por exemplo, você desejar baixar simultaneamente várias páginas para concatená-las em uma única página grande, inicie downloads simultâneos usando threads, mas precisará aguardar até que a última página / thread seja concluída antes de começar a montar uma única página de muitos. É quando você usa
join()
.fonte
demon_thread.join(0.0)
,join()
é, por padrão o bloqueio sem levar em conta o atributo daemon. Mas ingressar em um segmento demonizado abre muito provavelmente uma lata de problemas! Agora estou considerando a possibilidade de remover ajoin()
chamada no meu pequeno diagrama para o daemon-thread ...daemon=True
, não precisamos dojoin()
que precisamosjoin()
no final do código?main thread
finalização, o programa será finalizado sem deixar que achild-thread(long)
execução seja executada por si mesma (ouchild-thread(long)
seja, não foi completamente concluída)?Diretamente dos documentos
Isso significa que a linha principal que gera
t
ed
aguarda ot
término até terminar.Dependendo da lógica empregada pelo seu programa, você pode esperar até que um encadeamento seja concluído antes que o encadeamento principal continue.
Também a partir dos documentos:
Um exemplo simples, digamos que temos o seguinte:
Que termina com:
Isso produzirá:
Aqui, o encadeamento mestre espera explicitamente que o
t
encadeamento seja concluído até que seja chamadoprint
pela segunda vez.Como alternativa, se tivéssemos isso:
Obteremos esta saída:
Aqui, realizamos nosso trabalho no thread principal e aguardamos o
t
término do thread. Nesse caso, podemos até remover a junção explícitat.join()
e o programa aguardará implicitamentet
a conclusão.fonte
t.join()
. adicionando sono profundo ou algo mais. No momento, posso ver qualquer alteração no programa, mesmo que eu o use ou não. mas para damemon eu posso ver sua saída se eu usard.join()
o que eu não ver quando eu não uso d.join ()Obrigado por esta discussão - também me ajudou muito.
Eu aprendi algo sobre .join () hoje.
Esses threads são executados em paralelo:
e estes são executados sequencialmente (não o que eu queria):
Em particular, eu estava tentando ser inteligente e arrumado:
Isso funciona! Mas é executado seqüencialmente. Eu posso colocar o self.start () em __ init __, mas não o self.join (). Isso tem que ser feito depois cada encadeamento.
join () é o que faz com que o thread principal aguarde o término do thread. Caso contrário, seu encadeamento será executado sozinho.
Portanto, uma maneira de pensar em join () como um "hold" no thread principal - meio que desassocia seu thread e é executado sequencialmente no thread principal, antes que o thread principal possa continuar. Assegura que seu encadeamento esteja completo antes que o encadeamento principal avance. Observe que isso significa que está tudo bem se o seu encadeamento já estiver concluído antes de você chamar o join () - o encadeamento principal é liberado imediatamente quando o join () é chamado.
De fato, agora me ocorre que o thread principal aguarda em d.join () até o thread d terminar antes de passar para t.join ().
De fato, para ser bem claro, considere este código:
Produz essa saída (observe como as instruções de impressão são encadeadas uma na outra.)
O t1.join () está mantendo o encadeamento principal. Todos os três encadeamentos são concluídos antes que o t1.join () termine e o encadeamento principal prossiga para executar a impressão, depois t2.join () e, em seguida, imprima e t3.join () e depois imprima.
Correções são bem-vindas. Eu também sou novo no segmento.
(Observação: caso você esteja interessado, estou escrevendo um código para um DrinkBot e preciso executar rosqueamentos para executar as bombas de ingredientes simultaneamente e não sequencialmente - menos tempo para aguardar cada bebida.)
fonte
O método join ()
Fonte: http://docs.python.org/2/library/threading.html
fonte
t.join()
e o programa ainda o espera antes do término. Eu não vejo nenhum usot.join()
aqui no meu códigoCompreensão simples,
with join - o intérprete aguardará até que seu processo seja concluído ou encerrado
sem ingresso - o intérprete não espera até que o processo seja encerrado ,
fonte
Ao criar
join(t)
funções para encadeamentos não daemon e encadeamento daemon, o encadeamento principal (ou processo principal) deve aguardart
segundos e pode ir além para trabalhar em seu próprio processo. Durante ost
segundos de espera, os dois segmentos filhos devem fazer o que podem, como imprimir algum texto. Após ost
segundos, se o encadeamento que não é daemon ainda não terminou seu trabalho, e ainda pode finalizá-lo após o processo principal concluir seu trabalho, mas para o encadeamento daemon, apenas perdeu a janela da oportunidade. No entanto, acabará por morrer após a saída do programa python. Por favor, corrija-me se houver algo errado.fonte
No python 3.x, join () é usado para ingressar em um encadeamento com o encadeamento principal, ou seja, quando join () é usado para um encadeamento específico, o encadeamento principal para de ser executado até que a execução do encadeamento unido seja concluída.
fonte
Este exemplo demonstra a
.join()
ação:Fora:
fonte
Existem alguns motivos para o thread principal (ou qualquer outro thread) ingressar em outros threads
Um encadeamento pode ter criado ou retido (bloqueado) alguns recursos. O encadeamento de chamada de associação pode conseguir limpar os recursos em seu nome
join () é uma chamada de bloqueio natural para o encadeamento de chamada de junção continuar após o término do encadeamento chamado.
Se um programa python não ingressar em outros threads, o interpretador python ainda ingressará em threads não daemon em seu nome.
fonte
"Qual é a utilidade de usar join ()?" você diz. Realmente, é a mesma resposta que "para que serve o fechamento de arquivos, já que o python e o sistema operacional fecharão meu arquivo para mim quando o programa terminar?".
É simplesmente uma questão de boa programação. Você deve juntar () seus tópicos no ponto no código em que o tópico não deve ser executado, porque você deve garantir positivamente que o thread não esteja em execução para interferir com seu próprio código ou se deseja se comportar corretamente em um sistema maior.
Você pode dizer "Não quero que meu código atrase a resposta" apenas por causa do tempo adicional que o join () pode exigir. Isso pode ser perfeitamente válido em alguns cenários, mas agora você precisa levar em consideração que seu código está "deixando um problema para que o python e o sistema operacional sejam limpos". Se você fizer isso por razões de desempenho, recomendo fortemente que você documente esse comportamento. Isto é especialmente verdade se você estiver construindo uma biblioteca / pacote que outros deverão utilizar.
Não há motivo para não entrar no (), além dos motivos de desempenho, e eu argumentaria que seu código não precisa ter um desempenho tão bom.
fonte
join()
.