O código a seguir leva a java.lang.IllegalThreadStateException: Thread already started
quando chamei o start()
método pela segunda vez no programa.
updateUI.join();
if (!updateUI.isAlive())
updateUI.start();
Isso acontece na segunda vez que updateUI.start()
é chamado. Passei por ele várias vezes e o thread é chamado e executado completamente antes de chegar updateUI.start()
.
Chamar updateUI.run()
evita o erro, mas faz com que o thread seja executado no thread de IU (o thread de chamada, conforme mencionado em outras postagens no SO), que não é o que eu quero.
Um Tópico pode ser iniciado apenas uma vez? Em caso afirmativo, o que devo fazer se quiser executar o tópico novamente? Este thread em particular está fazendo alguns cálculos em segundo plano, se eu não fizer isso no thread, então será feito no thread de interface do usuário e o usuário terá uma espera excessivamente longa.
Respostas:
Na Especificação da API Java para o
Thread.start
método:Além disso:
Portanto, sim, um
Thread
só pode ser iniciado uma vez.Se um
Thread
precisar ser executado mais de uma vez, deve-se fazer uma nova instância deThread
e chamástart
-lo.fonte
Thread
cada vez. Em vez disso, ele deve enviar a tarefa a um pool de threads (por exemplo,java.util.concurrent.ThreadPoolExecutor
)Exatamente certo. Da documentação :
Em termos do que você pode fazer para cálculos repetidos, parece que você poderia usar o método invokeLater do SwingUtilities . Você já está experimentando chamar
run()
diretamente, o que significa que já está pensando em usar um emRunnable
vez de um rawThread
. Tente usar oinvokeLater
método apenas naRunnable
tarefa e veja se isso se encaixa um pouco melhor no seu padrão mental.Aqui está o exemplo da documentação:
Se você substituir essa
println
chamada pelo seu cálculo, pode ser exatamente o que você precisa.EDITAR: dando seguimento ao comentário, não tinha percebido a tag Android no post original. O equivalente a invokeLater no trabalho do Android é
Handler.post(Runnable)
. De seu javadoc:Portanto, no mundo Android, você pode usar o mesmo exemplo acima, substituindo o
Swingutilities.invokeLater
com a postagem apropriada para aHandler
.fonte
RunOnUIThread(Runnable)
ou emView.post(Runnable)
vez de criar seu próprio Handler. Eles irão executar o executável no thread principal, permitindo que você atualize a IU.A resposta recém-chegada explica por que você não deve fazer o que está fazendo. Aqui estão algumas opções para resolver seu problema real.
Despeje seu próprio tópico e use
AsyncTask
.Ou crie um novo tópico quando precisar.
Ou configure seu thread para operar fora de uma fila de trabalho (por exemplo,
LinkedBlockingQueue
) em vez de reiniciar o thread.fonte
Não , não podemos iniciar o Thread novamente, isso lançará runtimeException java.lang.IllegalThreadStateException. >
Vamos dar um exemplo - pensar em iniciar a thread novamente e chamar o método start () nela (que internamente chamará o método run ()) para nós é algo como pedir a um homem morto para acordar e correr. Como, após completar sua vida, a pessoa vai para o estado morto.
verifique isso
fonte
O que você deve fazer é criar um Runnable e envolvê-lo com um novo Thread cada vez que quiser executar o Runnable. Seria muito feio de se fazer, mas você pode encapsular um encadeamento com outro encadeamento para executar o código para ele novamente, mas só fazer isso é realmente necessário.
fonte
Como você disse, um tópico não pode ser iniciado mais de uma vez.
Direto da boca do cavalo: Java API Spec
Se você precisar executar novamente o que quer que esteja acontecendo em seu thread, você terá que criar um novo thread e executá-lo.
fonte
Reutilizar um thread é uma ação ilegal na API Java. No entanto, você pode envolvê-lo em um implemento executável e executar novamente essa instância.
fonte
Sim, não podemos iniciar o thread já em execução. Ele lançará IllegalThreadStateException em tempo de execução - se o segmento já foi iniciado.
E se você realmente precisar iniciar o thread: Opção 1) Se um Thread precisar ser executado mais de uma vez, deve-se fazer uma nova instância do Thread e chamar start nele.
fonte
Sim. Você pode iniciá-lo exatamente uma vez.
Não execute o
Thread
novamente. Em vez disso, crie Runnable e publique-o no Handler de HandlerThread . Você pode enviar váriosRunnable
objetos. Se quiser enviar dados de volta ao UI Thread, com seuRunnable
run()
método, poste umMessage
noHandler
UI Thread e processehandleMessage
Consulte esta postagem para obter um exemplo de código:
Android: brinde em uma conversa
fonte
Não sei se é uma boa prática, mas quando deixo run () ser chamado dentro do método run (), ele não gera nenhum erro e realmente faz exatamente o que eu queria.
Eu sei que não é um tópico de discussão novamente, mas talvez isso seja útil para você.
Espero que isso ajude, mesmo que seja só um pouco.
Felicidades
fonte
Tive que consertar um vazamento de recursos causado por um programador que criou um Thread, mas em vez de iniciá-lo (), ele chamou o método run () - diretamente. Portanto, evite-o, a menos que você realmente saiba quais efeitos colaterais ele causa.
fonte
run()
diretamente, apenas incorporar um Runnable em um Thread e presumivelmente invocarstart()
.