1. Retorne dados por meio de variáveis e métodos de classe
Usar este método para retornar dados requer chamar o método start antes que os dados possam ser obtidos por meio de variáveis de classe ou métodos. Vamos primeiro ver quais resultados obtemos no Exemplo 2-13.
Copie o código do código da seguinte forma:
pacote mitoread;
classe pública MyThread estende Thread
{
string privada valor1;
string privada valor2;
execução de vazio público ()
{
value1 = "Retornar dados por meio de variáveis de membro";
value2 = "Retornar dados através do método membro";
}
public static void main(String[] args) lança exceção
{
thread MyThread = new MyThread();
thread.start();
System.out.println("valor1:" + thread.valor1);
System.out.println("valor2:" + thread.valor2);
}
}
A execução do código acima pode gerar os seguintes resultados:
Copie o código do código da seguinte forma:
valor1:nulo
valor2:nulo
Os resultados de execução acima parecem muito anormais. Os valores foram atribuídos a valor1 e valor2 no método run, mas null é retornado. A razão pela qual isso acontece é que os valores de valor1 e valor2 são gerados imediatamente após chamar o método start, e o método run aqui ainda não executou as instruções que atribuem valores a valor1 e valor2. Para evitar essa situação, você precisa esperar até que o método run seja executado antes de executar o código que gera valor1 e valor2. Portanto, podemos pensar em usar o método sleep para atrasar o thread principal. Por exemplo, podemos adicionar a seguinte instrução após thread.start():
dormir(1000);
Fazer isso pode atrasar o thread principal por 1 segundo antes de continuar, mas há um problema com isso, ou seja, como sabemos quanto tempo atrasar. Neste exemplo, existem apenas duas instruções de atribuição no método run e apenas um thread é criado. Portanto, um atraso de 1 segundo é suficiente, mas se as instruções no método run forem complexas, esse tempo será difícil de prever. Portanto, este método não é estável.
Nosso objetivo é obter os valores de valor1 e valor2, portanto, só precisamos determinar se valor1 e valor2 são nulos. Se nenhum deles for nulo, esses dois valores poderão ser gerados. Podemos usar o seguinte código para atingir esse propósito:
Copie o código do código da seguinte forma:
while (thread.value1 == nulo || thread.value2 == nulo);
Usar a instrução acima pode evitar essa situação de maneira muito estável, mas esse método consome muitos recursos do sistema. Você pode imaginar que se o código no método run for muito complexo, valor1 e valor2 levarão muito tempo para serem atribuídos, então o loop while deve continuar a ser executado até que valor1 e valor2 não estejam vazios. Portanto, podemos fazer as seguintes melhorias na afirmação acima:
Copie o código do código da seguinte forma:
while (thread.value1 == nulo || thread.value2 == nulo)
dormir(100);
No loop while, após julgar os valores de valor1 e valor2 pela primeira vez, ele dorme por 100 milissegundos e então julga esses dois valores. Isso ocupará menos recursos do sistema.
Embora o método acima possa ser resolvido muito bem, o modelo de threading do Java nos fornece uma solução melhor, que é o método join. Conforme discutido anteriormente, a função do join é usar threads para mudar da execução assíncrona para a execução síncrona. Quando o thread é executado de forma síncrona, não é diferente de obter os dados de retorno de um método comum. Portanto, esse problema pode ser resolvido de forma mais eficiente usando código como o seguinte:
Copie o código do código da seguinte forma:
thread.start();
thread.join();
Após thread.join() ser executado, o método run do thread foi encerrado, o que significa que o thread foi encerrado. Portanto, você pode usar com segurança qualquer recurso da classe MyThread após thread.join() para obter os dados retornados.
2. Retornar dados por meio da função de retorno de chamada
Na verdade, este método foi introduzido em "Três métodos de passagem de dados para threads". No exemplo do artigo "Três métodos de passagem de dados para threads", os resultados do cálculo são passados para o thread por meio do método de processo da classe Work, mas ao mesmo tempo, três números aleatórios também são obtidos do thread por meio do método de processo. Portanto, esse método pode passar e obter dados do thread.