Multithreading em Java
Qualquer aplicativo pode ter vários processos (instâncias). Cada um desses processos pode ser atribuído como um único thread ou como vários threads. Veremos neste tutorial como realizar múltiplas tarefas ao mesmo tempo e também aprenderemos mais sobre threads e sincronização entre threads.
O que é thread único?
Um único tópico em Java é basicamente uma unidade de processamento leve e menor. Java usa threads usando uma “Thread Class”. Existem dois tipos de thread – thread de usuário e thread daemon (os threads daemon são usados quando queremos limpar o aplicativo e são usados em segundo plano). Quando um aplicativo é iniciado pela primeira vez, o thread do usuário é criado. Depois disso, podemos criar muitos threads do usuário e threads daemon.
Exemplo de thread único:
package demotest; public class GuruThread { public static void main(String[] args) { System.out.println("Single Thread"); } }
Vantagens do thread único:
- Reduz a sobrecarga no aplicativo à medida que um único thread é executado no sistema
- Além disso, reduz o custo de manutenção do aplicativo.
O que é multithreading Java?
multithreading in Java é um processo de execução de dois ou mais threads simultaneamente para utilização máxima da CPU. Os aplicativos multithread executam dois ou mais threads simultaneamente. Portanto, também é conhecido como Concorrência em Java. Cada thread corre paralelamente um ao outro. Vários threads não alocam áreas de memória separadas, portanto, economizam memória. Além disso, a alternância de contexto entre threads leva menos tempo.
Exemplo de multithread:
package demotest; public class GuruThread1 implements Runnable { public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
Vantagens do multithread:
- Os usuários não são bloqueados porque os threads são independentes e às vezes podemos realizar várias operações
- Como tal, os threads são independentes, os outros threads não serão afetados se um thread atender a uma exceção.
Ciclo de vida do thread em Java
O ciclo de vida de um thread:
Existem vários estágios do ciclo de vida do thread, conforme mostrado no diagrama acima:
- Novo
- Executável
- Corrida
- Esperando
- Morto
- Novo: Nesta fase, o thread é criado utilizando a classe “Thread class”. Ele permanece neste estado até o programa começa o segmento. Também é conhecido como fio nascido.
- Executável: Nesta página, a instância do thread é invocada com um método start. O controle do thread é dado ao agendador para finalizar a execução. Depende do agendador se o thread deve ser executado.
- Corrida: Quando o thread começa a ser executado, o estado é alterado para o estado “em execução”. O agendador seleciona um thread do pool de threads e começa a ser executado no aplicativo.
- Esperando: Este é o estado em que um thread deve esperar. Como há vários threads em execução no aplicativo, há necessidade de sincronização entre os threads. Portanto, um thread tem que esperar até que o outro thread seja executado. Portanto, este estado é referido como estado de espera.
- Morto: Este é o estado quando o thread é encerrado. O thread está em estado de execução e assim que conclui o processamento ele está em “estado morto”.
Métodos de Multithreading em Java
Alguns dos métodos comumente usados para threads são:Forma | Descrição |
---|---|
começar() | Este método inicia a execução do thread e JVM chama o método run() no thread. |
Dormir (int milissegundos) | Este método faz o thread dormir, portanto a execução do thread será pausada por milissegundos fornecidos e depois disso, o thread começará a ser executado novamente. Isso ajuda na sincronização dos threads. |
getName () | Ele retorna o nome do thread. |
setPriority(int novaprioridade) | Isso altera a prioridade do thread. |
colheita () | Isso faz com que o thread atual seja interrompido e outros threads sejam executados. |
Exemplo: Neste programa multithreading em Java Por exemplo, vamos criar um thread e explorar métodos integrados disponíveis para threads.
package demotest; public class thread_example1 implements Runnable { @Override public void run() { } public static void main(String[] args) { Thread guruthread1 = new Thread(); guruthread1.start(); try { guruthread1.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } guruthread1.setPriority(1); int gurupriority = guruthread1.getPriority(); System.out.println(gurupriority); System.out.println("Thread Running"); } }
Explicação do código:
- Linha de código 2: Estamos criando uma classe “thread_Example1” que implementa a interface Runnable (ela deve ser implementada por qualquer classe cujas instâncias sejam executadas pelo thread).
- Linha de código 4: Ele substitui o método run da interface executável, pois é obrigatório substituir esse método
- Linha de código 6: Aqui definimos o método principal no qual iniciaremos a execução do thread.
- Linha de código 7: Aqui estamos criando um novo nome de thread como “guruthread1” instanciando uma nova classe de thread.
- Linha de código 8: usaremos o método “start” do thread usando a instância “guruthread1”. Aqui o thread começará a ser executado.
- Linha de código 10: Aqui estamos usando o método “sleep” do thread usando a instância “guruthread1”. Conseqüentemente, o thread ficará suspenso por 1000 milissegundos.
- Código 9-14: Aqui colocamos o método sleep no bloco try catch, pois há uma exceção verificada que ocorre, ou seja, exceção interrompida.
- Linha de código 15: Aqui estamos definindo a prioridade do thread para 1 de qualquer prioridade que fosse
- Linha de código 16: Aqui estamos obtendo a prioridade do thread usando getPriority()
- Linha de código 17: Aqui estamos imprimindo o valor obtido em getPriority
- Linha de código 18: Aqui estamos escrevendo um texto que o tópico está rodando.
Ao executar o código acima, você obtém a seguinte saída:
Saída:
5 é a prioridade do Thread e Thread Running é o texto que é a saída do nosso código.
Java Fio Synchronização
Em multithreading, há o comportamento assíncrono dos programas. Se um thread estiver gravando alguns dados e outro thread estiver lendo dados ao mesmo tempo, pode criar inconsistência no aplicativo. Quando há necessidade de acessar os recursos compartilhados por dois ou mais threads, então a abordagem de sincronização é utilizada. Java forneceu métodos sincronizados para implementar comportamento sincronizado.
Nessa abordagem, uma vez que o thread alcança o bloco synchronized, então nenhum outro thread pode chamar esse método no mesmo objeto. Todos os threads têm que esperar até que o thread termine o bloco synchronized e saia dele. Dessa forma, a sincronização ajuda em um aplicativo multithread. Um thread tem que esperar até que outro thread termine sua execução, somente então os outros threads são permitidos para execução.
Pode ser escrito da seguinte forma:
Synchronized(object) { //Block of statements to be synchronized }
Multithreading em Java Programas de exemplo
Neste multithreading Java Por exemplo, pegaremos dois threads e buscaremos os nomes dos threads.
Exemplo1:
GuruThread1.java package demotest; public class GuruThread1 implements Runnable{ /** * @param args */ public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
Explicação do código:
- Linha de código 3: Pegamos uma classe “GuruThread1” que implementa Runnable (deve ser implementada por qualquer classe cujas instâncias sejam executadas pelo thread).
- Linha de código 8: Este é o método principal da classe
- Linha de código 9: Aqui estamos instanciando a classe Thread e criando uma instância chamada “guruThread1” e criando um thread.
- Linha de código 10: Aqui estamos instanciando a classe Thread e criando uma instância chamada “guruThread2” e criando um thread.
- Linha de código 11: Estamos iniciando o tópico, ou seja, guruThread1.
- Linha de código 12: Estamos iniciando o tópico, ou seja, guruThread2.
- Linha de código 13: Produzindo o texto como “Os nomes dos threads são os seguintes:”
- Linha de código 14: Obtendo o nome do thread 1 usando o método getName() da classe thread.
- Linha de código 15: Obtendo o nome do thread 2 usando o método getName() da classe thread.
Ao executar o código acima, você obtém a seguinte saída:
Saída:
Os nomes dos threads estão sendo exibidos aqui como
- Guru1
- Guru2
2 exemplo:
Neste multithreading em Java Por exemplo, aprenderemos sobre como substituir os métodos run() e start() de uma interface executável e criar dois threads dessa classe e executá-los de acordo.
Além disso, estamos tendo duas aulas,
- Um que implementará a interface executável e
- Outro que terá o método principal e será executado de acordo.
package demotest; public class GuruThread2 { public static void main(String[] args) { // TODO Auto-generated method stub GuruThread3 threadguru1 = new GuruThread3("guru1"); threadguru1.start(); GuruThread3 threadguru2 = new GuruThread3("guru2"); threadguru2.start(); } } class GuruThread3 implements Runnable { Thread guruthread; private String guruname; GuruThread3(String name) { guruname = name; } @Override public void run() { System.out.println("Thread running" + guruname); for (int i = 0; i < 4; i++) { System.out.println(i); System.out.println(guruname); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Thread has been interrupted"); } } } public void start() { System.out.println("Thread started"); if (guruthread == null) { guruthread = new Thread(this, guruname); guruthread.start(); } } }
Explicação do código:
- Linha de código 2: Aqui estamos pegando uma classe “GuruThread2” que conterá o método principal.
- Linha de código 4: Aqui estamos pegando um método principal da classe.
- Linha de código 6-7: Aqui estamos criando uma instância da classe GuruThread3 (que é criada nas linhas abaixo do código) como “threadguru1” e estamos iniciando o thread.
- Linha de código 8-9: Aqui estamos criando outra instância da classe GuruThread3 (que é criada nas linhas abaixo do código) como “threadguru2” e estamos iniciando o thread.
- Linha de código 11: Aqui estamos criando uma classe “GuruThread3” que implementa a interface executável (ela deve ser implementada por qualquer classe cujas instâncias se destinam a ser executadas pelo thread).
- Linha de código 13-14: estamos pegando duas variáveis de classe, das quais uma é do tipo classe thread e outra da classe string.
- Linha de código 15-18: estamos substituindo o construtor GuruThread3, que usa um argumento como tipo de string (que é o nome do thread) que é atribuído à variável de classe guruname e, portanto, o nome do thread é armazenado.
- Linha de código 20: Aqui estamos substituindo o método run() da interface executável.
- Linha de código 21: Estamos gerando o nome do thread usando a instrução println.
- Linha de código 22-31: Aqui estamos usando um loop for com contador inicializado em 0, e não deve ser menor que 4 (podemos pegar qualquer número, portanto aqui o loop será executado 4 vezes) e incrementando o contador. Estamos imprimindo o nome do thread e também fazendo com que o thread fique suspenso por 1000 milissegundos dentro de um bloco try-catch, pois o método sleep gerou uma exceção verificada.
- Linha de código 33: Aqui estamos substituindo o método start da interface executável.
- Linha de código 35: Estamos exibindo o texto “Tópico iniciado”.
- Linha de código 36-40: Aqui estamos adotando uma condição if para verificar se a variável de classe guruthread tem valor ou não. Se for nulo, então estamos criando uma instância usando a classe thread que leva o nome como parâmetro (valor para o qual foi atribuído no construtor). Depois disso, o thread é iniciado usando o método start().
Ao executar o código acima você obtém a seguinte saída:
saída:
Existem dois threads, portanto, recebemos duas vezes a mensagem “Tópico iniciado”.
Obtemos os nomes dos threads conforme os geramos.
Ele entra no loop for onde imprimimos o contador e o nome do thread e o contador começa com 0.
O loop é executado três vezes e entre o thread fica inativo por 1000 milissegundos.
Portanto, primeiro obtemos guru1, depois guru2 e novamente guru2 porque o thread dorme aqui por 1000 milissegundos e depois o próximo guru1 e novamente guru1, o thread dorme por 1000 milissegundos, então obtemos guru2 e depois guru1.
Resumo
Neste tutorial, vimos aplicativos multithread em Java e como usar thread único e multi thread em Java.
- Explique multithreading em Java: no multithreading, os usuários não são bloqueados, pois os threads são independentes e podem executar várias operações ao mesmo tempo
- Vários estágios do ciclo de vida do fio são,
- Novo
- Executável
- Corrida
- Esperando
- Morto
- Também aprendemos sobre Sincronização entre threads, o que ajuda o aplicativo a funcionar sem problemas.
- Programação multithread em Java facilita muito mais tarefas de aplicação.