Estou escrevendo um aplicativo que possui 5 threads que obtêm algumas informações da web simultaneamente e preenchem 5 campos diferentes em uma classe de buffer.
Preciso validar os dados do buffer e armazená-los em um banco de dados quando todos os threads terminarem seu trabalho.
Como posso fazer isso (ser alertado quando todos os threads concluírem seu trabalho)?
java
multithreading
wait
RYN
fonte
fonte
Respostas:
A abordagem que utilizo é usar um ExecutorService para gerenciar pools de threads.
fonte
while(!es.awaitTermination(1, TimeUnit.MINUTES));
es.shutdown();
? e se eu escrever um código no qual execute um thread usandoes.execute(runnableObj_ZipMaking);
emtry
bloco e emfinally
eu chameboolean finshed = es.awaitTermination(10, TimeUnit.MINUTES);
. Portanto, suponho que isso deva esperar até que todos os threads concluam seu trabalho ou o tempo limite ocorra (o que ocorrer primeiro). Minha suposição está correta? ou ligar parashutdown()
é obrigatório?Você pode
join
para os tópicos. A junção bloqueia até que o thread seja concluído.Observe que
join
lança umInterruptedException
. Você terá que decidir o que fazer se isso acontecer (por exemplo, tentar cancelar os outros threads para evitar que trabalho desnecessário seja feito).fonte
t.join();
significa que o thread atual bloqueia até que o threadt
termine. Não afeta o segmentot
.Dê uma olhada em várias soluções.
join()
API foi introduzida nas primeiras versões do Java. Algumas boas alternativas estão disponíveis com este pacote simultâneo desde o lançamento do JDK 1.5.ExecutorService # invokeAll ()
Consulte esta questão SE relacionada para obter um exemplo de código:
Como usar invokeAll () para permitir que todos os conjuntos de threads realizem suas tarefas?
CountDownLatch
Consulte esta pergunta para o uso de
CountDownLatch
Como esperar por um segmento que gera seu próprio segmento?
ForkJoinPool ou newWorkStealingPool () em Executores
Iterar por meio de todos os objetos Future criados após o envio para
ExecutorService
fonte
Além do
Thread.join()
sugerido por outros, o java 5 introduziu a estrutura do executor. Lá você não trabalha comThread
objetos. Em vez disso, você envia seus objetosCallable
ouRunnable
a um executor. Existe um executor especial que se destina a executar várias tarefas e retornar seus resultados fora de ordem. Esse é oExecutorCompletionService
:Em seguida, você pode chamar repetidamente
take()
até que não haja maisFuture<?>
objetos para retornar, o que significa que todos eles estão concluídos.Outra coisa que pode ser relevante, dependendo do seu cenário é
CyclicBarrier
.fonte
executor.submit
retorna aFuture<?>
. Eu acrescentaria esses futuros a uma lista e, em seguida, percorreria a lista chamandoget
cada futuro.Executors
, por exemplo,Executors.newCachedThreadPool
(ou semelhante)Outra possibilidade é o
CountDownLatch
objeto, que é útil para situações simples: já que você sabe de antemão o número de threads, você inicializa com a contagem relevante e passa a referência do objeto para cada thread.Após a conclusão de sua tarefa, cada thread chama o
CountDownLatch.countDown()
que diminui o contador interno. O thread principal, após iniciar todos os outros, deve fazer aCountDownLatch.await()
chamada de bloqueio. Ele será liberado assim que o contador interno atingir 0.Preste atenção que com este objeto, um também
InterruptedException
pode ser lançado.fonte
Você faz
Após este loop for, você pode ter certeza de que todos os threads concluíram seus trabalhos.
fonte
Espere / bloqueie o Thread Principal até que outros threads concluam seu trabalho.
Como
@Ravindra babu
disse, pode ser alcançado de várias formas, mas mostrando com exemplos.java.lang.Thread. join () Desde: 1.0
java.util.concurrent.CountDownLatch desde: 1.5
.countDown()
«Diminui a contagem do grupo de trava..await()
«Os métodos de espera bloqueiam até que a contagem atual chegue a zero.Se você criou
latchGroupCount = 4
entãocountDown()
deve ser chamado 4 vezes para fazer contar 0. Então, issoawait()
irá liberar os threads de bloqueio.Exemplo de código da classe Threaded
LatchTask
. Para testar o uso da abordagemjoiningThreads();
elatchThreads();
do método principal.Estrutura do executor : podemos usar ExecutorService para criar um pool de threads e rastrear o progresso das tarefas assíncronas com Future.
submit(Runnable)
,submit(Callable)
que retorna Objeto Futuro. Ao usar afuture.get()
função, podemos bloquear o thread principal até que os threads de trabalho concluam seu trabalho.invokeAll(...)
- retorna uma lista de objetos Future por meio dos quais você pode obter os resultados das execuções de cada Callable.Encontre exemplos de uso de Interfaces Runnable, Callable with Executor framework.
@Veja também
fonte
Armazene os objetos Thread em alguma coleção (como uma List ou Set) e, em seguida, faça um loop pela coleção assim que os threads forem iniciados e chame join () nos Threads.
fonte
Você pode usar o método Threadf # join para essa finalidade.
fonte
Embora não seja relevante para o problema do OP, se você estiver interessado na sincronização (mais precisamente, um rendez-vous) com exatamente um thread, você pode usar um Exchanger
No meu caso, precisei pausar o thread pai até que o thread filho fizesse algo, por exemplo, concluía sua inicialização. Um CountDownLatch também funciona bem.
fonte
Um serviço de executor pode ser usado para gerenciar vários threads, incluindo status e conclusão. Veja http://programmingexamples.wikidot.com/executorservice
fonte
tente isso, vai funcionar.
fonte
Tive um problema semelhante e acabei usando Java 8 parallelStream.
É super simples e legível. Nos bastidores, ele está usando o pool de junção de bifurcação padrão da JVM, o que significa que ele aguardará a conclusão de todos os encadeamentos antes de continuar. Para o meu caso, foi uma solução bacana, porque era o único parallelStream em meu aplicativo. Se você tiver mais de um parallelStream em execução simultaneamente, leia o link abaixo.
Mais informações sobre fluxos paralelos aqui .
fonte
As respostas existentes disse que poderia
join()
cada segmento.Mas existem várias maneiras de obter a lista / array de threads:
ThreadGroup
para gerenciar os threads.O código a seguir usará a
ThreadGruop
abordagem. Ele cria um grupo primeiro, então ao criar cada thread especifica o grupo no construtor, mais tarde pode obter a matriz de thread por meio deThreadGroup.enumerate()
Código
SyncBlockLearn.java
O encadeamento principal aguardará que todos os encadeamentos do grupo sejam concluídos.
fonte
Criei um pequeno método auxiliar para aguardar a conclusão de alguns Threads:
fonte
Use isto em seu thread principal: while (! Executor.isTerminated ()); Coloque esta linha de código após iniciar todos os threads do serviço do executor. Isso só iniciará o thread principal depois que todos os threads iniciados pelos executores forem concluídos. Certifique-se de chamar executor.shutdown (); antes do loop acima.
fonte