JavaRush /Blogue Java /Random-PT /Multithreading: o que os métodos de classe de thread faze...

Multithreading: o que os métodos de classe de thread fazem

Publicado no grupo Random-PT
Olá! Hoje continuamos falando sobre multithreading. Vamos dar uma olhada na classe Thread e como seus diversos métodos funcionam. Anteriormente, quando estudávamos métodos de classe, na maioria das vezes simplesmente escrevíamos assim: “nome do método” -> “o que ele faz”.
Multithreading: o que fazem os métodos da classe Thread - 1
Isso não funcionará com métodos Thread :) A lógica deles é mais complicada e sem vários exemplos é impossível de entender.

Método Thread.start()

Vamos começar com a repetição. Como você provavelmente se lembra, você pode criar um thread herdando sua classe da classe Threade substituindo o método nela run(). Mas, é claro, não começará sozinho. Para fazer isso, chamamos o método em nosso objeto start(). Multithreading: o que fazem os métodos da classe Thread - 2Vamos lembrar o exemplo da palestra anterior:
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Выполнен поток " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Observação: para iniciar um tópico, você deve chamar o método especialstart(), não orun()! Este é um erro fácil de cometer, especialmente quando se aprende multithreading pela primeira vez. Se em nosso exemplo você chamar um método em um objeto 10 vezesrun()em vez destart(), o resultado será assim:
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Thread-0 thread executado Thread-1 thread executado Thread-2 thread executado Thread-3 thread executado Thread-4 thread executado Thread-5 thread executado Thread-6 thread executado Thread-7 thread executado Thread-8 thread executado Thread-9 thread executado Observe a sequência de saída: tudo corre estritamente em ordem. Estranho, certo? Não estamos acostumados com isso, pois já sabemos que a ordem em que os threads são lançados e executados é determinada pela superinteligência dentro do nosso sistema operacional - o agendador de threads. Talvez eu tenha tido sorte? Claro, não é uma questão de sorte. Você pode verificar isso executando o programa mais algumas vezes. A questão é que chamar um método diretamenterun()não tem nada a ver com multithreading. Neste caso, o programa será executado na thread principal - aquela em que o método é executadomain(). Ele simplesmente enviará 10 linhas sequencialmente para o console e pronto. Não serão iniciados 10 tópicos. Portanto, lembre-se do futuro e verifique-se constantemente. Se você quiser que isso seja feitorun(), ligue para elestart(). Vamos continuar.

Método Thread.sleep()

Para pausar a execução do thread atual por algum tempo, use o arquivo sleep(). Multithreading: o que fazem os métodos da classe Thread - 3O método sleep()toma como parâmetro o número de milissegundos, ou seja, o tempo durante o qual a thread precisa ser colocada em hibernação.
public class Main {

   public static void main(String[] args) throws InterruptedException {

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - Сколько я проспал? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " секунды");

   }
}
Saída do console: - Quanto tempo eu dormi? - 3 segundos Observação: o método sleep()é estático: ele coloca o thread atual em suspensão. Ou seja, aquele que está funcionando no momento. Outra nuance importante: o fluxo no estado de sono pode ser interrompido. Neste caso, ocorrerá uma exceção no programa InterruptedException. Veremos um exemplo abaixo. Aliás, o que acontece depois que o tópico “acorda”? Continuará imediatamente a sua execução de onde parou? Não. Depois que o thread é ativado - quando o tempo passado como argumento expira Thread.sleep()- ele entra no estado executável . No entanto, isso não significa que o agendador de threads irá executá-lo. É bem possível que dê preferência a algum outro tópico “não adormecido”, e nosso tópico “recém-despertado” continue funcionando um pouco mais tarde. Lembre-se: “acordar não significa continuar trabalhando naquele exato segundo!”

Método Thread.join()

Multithreading: o que fazem os métodos da classe Thread - 4O método join()suspende a execução do thread atual até que outro thread seja concluído. Se tivermos 2 threads, t1e t2, e escrevermos -
t1.join()
t2não começará a funcionar até que t1 conclua seu trabalho. O método join()pode ser usado para garantir a sequência de execução dos threads. Vejamos o trabalho join()usando um exemplo:
public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Начало работы потока " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Поток " + getName() +  " завершил работу.");
   }
}


public class Main {

   public static void main(String[] args) throws InterruptedException {

       ThreadExample t1 = new ThreadExample();
       ThreadExample t2 = new ThreadExample();

       t1.start();


 /*Второй поток t2 начнет выполнение только после того, How будет завершен
       (or бросит исключение) первый поток - t1*/
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       //Главный поток продолжит работу только после того, How t1 и t2 завершат работу
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("Все потоки закончor работу, программа завершена");

   }
}
Criamos uma classe simples ThreadExample. Sua tarefa é exibir na tela uma mensagem sobre o início dos trabalhos, adormecer por 5 segundos e ao final informar sobre a conclusão dos trabalhos. Nada complicado. A lógica principal está contida na classe Main. Veja os comentários: usando o método, join()controlamos com sucesso a sequência de execução dos threads. Se você se lembra do início do tópico, o agendador de threads fez isso. Ele os lançou a seu critério: cada vez de forma diferente. Aqui, usando o método, garantimos que primeiro o thread seria lançado e executado t1, depois o thread t2e somente depois o thread principal de execução do programa. Vá em frente. Em programas reais, muitas vezes você encontrará situações em que precisará interromper a execução de algum thread. Por exemplo, nosso thread está em execução, mas aguarda que um determinado evento ou condição seja atendido. Se isso acontecer, ele para. Provavelmente seria lógico se existisse algum método como stop(). Porém, nem tudo é tão simples. Era uma vez um método Thread.stop()em Java que realmente existia e permitia interromper o trabalho de um thread. Mais tarde, porém, foi removido da biblioteca Java. Você pode procurar na documentação do Oracle e ver que ele está marcado como obsoleto . Por que? Porque simplesmente interrompeu o fluxo sem nenhum trabalho adicional. Por exemplo, um thread pode trabalhar com dados e alterar algo neles. Então ele foi nocauteado abruptamente stop()no meio do trabalho - e foi isso. Não houve desligamento correto, nem liberação de recursos, nem mesmo tratamento de erros – nada disso aconteceu. O método stop(), para exagerar, simplesmente destruiu tudo em seu caminho. Seu funcionamento pode ser comparado ao modo como alguém tira o plugue da tomada para desligar um computador. Sim, você pode alcançar o resultado desejado. Mas todos entendem que em algumas semanas o computador não dirá “obrigado” por isso. Por esse motivo, a lógica de interrupção de threads em Java foi alterada e agora é utilizado um método especial - interrupt().

Método Thread.interrupt()

O que acontece se você chamar um método interrupt() em um thread ? Existem 2 opções:
  1. Se o objeto estava no estado de espera naquele momento, por exemplo, joinou sleep, a espera será interrompida e o programa lançará InterruptedException.
  2. Se o thread estava funcionando naquele momento, o sinalizador booleano do objeto será definido interrupted.
Mas teremos que verificar o objeto quanto ao valor deste sinalizador e concluir o trabalho corretamente! Para isso, a classe Threadpossui um método especial - boolean isInterrupted(). Voltemos ao exemplo do relógio da aula principal. Por conveniência, é um pouco simplificado:
public class Clock extends Thread {

   public static void main(String[] args) throws InterruptedException {
       Clock clock = new Clock();
       clock.start();

       Thread.sleep(10000);
       clock.interrupt();
   }

   public void run() {
       Thread current = Thread.currentThread();

       while (!current.isInterrupted())
       {
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               System.out.println("Работа потока была прервана");
               break;
           }
           System.out.println("Tik");
       }
   }
}
No nosso caso, o relógio começa e começa a contar a cada segundo. No 10º segundo interrompemos o fluxo do relógio. Como você já sabe, se o thread que estamos tentando interromper estiver em um dos estados de espera, isso resultará em InterruptedException. Este tipo de exceção é uma exceção verificada, portanto pode ser facilmente capturada e nossa lógica de encerramento do programa executada. Foi isso que fizemos. Aqui está o nosso resultado: Tik Tik Tik Tik Tik Tik Tik Tik Tik O trabalho da thread foi interrompido, o que conclui nossa introdução aos principais métodos da classe Thread. Para consolidar seu conhecimento, você pode assistir a esta vídeo-aula sobre multithreading:
servirá como excelente material adicional! Ao final, após uma visão geral dos métodos, conta exatamente o que passaremos a seguir no curso :) Boa sorte!
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION