Aguarde...

Usando Thread em Java

Publicado em 07/07/2014

Thread

Thread

Introdução

Aplicações modernas necessitam ser mais que uma simples sequência de processos, não pode mais apenas executar uma série de ações enfileiradas como se fossem um script, precisam ser multi-tarefas, precisam executar várias ações simultaneamente. Não vou entrar em muita teoria nesse artigo, afinal, para isso existem os livros, vamos direto ao ponto com uma explicação prática!

O que é uma Thread?

Analogia com bolinha

Analogia com bolinha

Uma Thread nada mais é do que um processo com sua própria pilha de chamadas. Ficou confuso? Vamos fazer uma analogia, imagine aquelas maquinas de soltar bolinhas que tinha antigamente, onde você colocava uma moeda, girava e saia uma bolinha. Agora imagine duas máquinas, uma com bolinhas brancas e outra com bolinhas pretas. Na frente dessas máquinas tem uma criança. Se a criança fosse tirar todas as bolinhas e dividir com outras crianças, sendo que algumas querem bolinha branca e outras preta. O que você recomendaria? Que a criança que está operando a máquina tire todas as brancas primeiro e depois tire as pretas? Mas enquanto as crianças que querem a branca vão recebendo suas bolinhas, as outras crianças que optaram pela preta ficam só chupando dedo, aguardando impacientemente que todas as bolinhas brancas acabem para que a criança que opera a máquina comece então a tirar as pretas. Como resolver o problema da ansiedade das crianças que querem bolinha preta? Simples! Peça que a criança que opera a máquina retire um branca e depois uma preta e vá intercalando dessa forma, uma branca e uma preta, uma branca e uma preta, e assim sucessivamente.

Para o mundo real

Toda aplicação em Java começa com uma única Thread já rodando. Todas as ações do softare vão sendo empilhadas nesse processo. Sendo assim, cada ação é executada logo após a outra. Comparando com o exemplo da bolinha, a máquina de bolinhas seria o processo e a criança seria o processador do computador. Em java, se quisermos que ações sejam executadas paralelamente, precisamos criar outra(s) Thread(s) para que os processos concorram ao uso do processador, fazendo com que hora um processo seja executado, outra outro, permitindo que os dois vá sendo executados paralelamente. No exemplo da bolinha, quando falamos pra criança tirar uma bolinha de cada máquina, ela não tira duas bolinhas ao mesmo tempo, apenas alterna de máquina, tirando sempre uma bolinha mas de forma alternada.

Situação prática

Vamos à uma situação prática usando Java. Vamos fazer dos laços de repetição simulando uma máquina de bolinhas. Primeiramente sem usar o recurso de multi-thread, depois faremos o segundo caso. No nosso exemplo existem 20 bolinhas, 10 brancas e 10 pretas.

Single-thread

Nesse exemplo vamos ver a distribuição das bolinhas apenas no modo single-thread

    public class SingleThread {

    public static void main(String[] args) throws InterruptedException {
        //Bolinhas brancas
        for (int i = 0; i < 10; i++) {
            System.out.println("BRANCA");
            Thread.sleep(1000); //Para demorar um segundo ate a proxima bolinha
        }

        //Bolinhas pretas
        for (int i = 0; i < 10; i++) {
            System.out.println("PRETA");
            Thread.sleep(1000); //Para demorar um segundo ate a proxima bolinha
        }
    }
}

Nesse exemplo será impresso 10 vezes a palavra "BRANCA" seguidamente e depois 10 vezes a palavra "PRETA"

Multi-thread

Nesse exemplo vamos ver a distribuição das bolinhas no modo multi-thread

    public class MultiThread {

    public static void main(String[] args) {

        /**
         * O primeiro passo e criar os Runnables
         */
        Runnable bolinhaBranca = new Runnable() {

            @Override
            public void run() {
                //Bolinhas brancas
                for (int i = 0; i < 10; i++) {
                    try {
                        System.out.println("BRANCA");
                        Thread.sleep(1000); //Para demorar um segundo ate a proxima bolinha
                    } catch (InterruptedException ex) {
                        System.out.println("A Thread sofreu uma interrupcao!");
                    }
                }
            }
        };

        Runnable bolinhaPreta = new Runnable() {

            @Override
            public void run() {
                //Bolinhas pretas
                for (int i = 0; i < 10; i++) {
                    try {
                        System.out.println("PRETA");
                        Thread.sleep(1000); //Para demorar um segundo ate a proxima bolinha
                    } catch (InterruptedException ex) {
                        System.out.println("A Thread sofreu uma interrupcao!");
                    }
                }
            }
        };
        
        
        /**
         * O segundo passo e agendar as Threads para rodar os Runnables 
         */
        
        Thread thBranca = new Thread(bolinhaBranca);
        Thread thPreta = new Thread(bolinhaPreta);
        
        /**
         * O terceiro passo e iniciar as threads.
         */
        
        thBranca.start();
        thPreta.start();
    }
}

Nesse exemplo será impresso a palavra "BRANCA" e "PRETA" de forma alternada, pois cada processo está fazendo o seu trabalho de forma individual. Teoricamente não poderia sair duas bolinhas brancas ou duas bolinhas pretas ao mesmo tempo, a questão é que depois que as Threads começam a rodar, a JVM elege a vez de quem vai ser executando seguindo seus próprios quesitos, pode acontecer de uma thread ser processada duas ou mais vezes sem que a outra tenha sido proceda ao menos vez.

Onde usar multi-thread

Uma aplicação real que use multi-thread poderia ser, por exemplo, um conversor de vídeo. Imagine que você escolha 10 videos para converter. O primeiro vídeo é grande e levaria 20 minutos pra ficar pronto. Porém, os outros 9 vídeos são pequenos e levariam um minuto cada um pra ser convertido. Então teriamos, teoricamente que esperar 29 minutos para que todos os videos fossem convertidos. Se a conversão começar pelo vídeo mais longo, você ficará olhando para a tela por 20 minutos achando que vai levar uma eternidade para tudo ficar pronto. Agora, se pra cada vídeo fosse usada uma Thread separada, vários vídeos seriam convertidos antes de 20 minutos, não quer dizer que a conversão seria mais rápido mas sim que fosse mais distribuída, no final das contas o tempo para converter tudo seria o mesmo.

Teoria ultra complexa das galaxias relativo a Thread

Esse artigo tentou ser o mais prático possível. Existe muito a ser falado sobre Thread, se você tiver mais dúvidas ou quiser entender a fundo recomendo pegar um livro que tenha um capítulo só sobre Thread, como por exemplo o Guia de Estudo SCJP de Kathy Sierra e Bert Bates.

Comentarios (3) para Usando Thread em Java

Elber,   17/07/2014

Muito obrigado amigo, estava com uma dúvida enorme e você me ajudou com este material. Abraço!

Henrique Soares,   15/08/2015

Exemplo simples e expetacular.

Ajudou muito como todos os outros artigos.

Gustavo Ferreira,   24/10/2015

www.gqferreira.com.br

Obrigado pessoal!

Gostou do artigo? Acha que poderia ser melhor em algum ponto? Dê o seu feedback!