Você está na página 1de 7

CURSO DE CIÊNCIA DA COMPUTAÇÃO

DISCIPLINA: DESENVOLVIMENTO DE APLICAÇÕES DISTRIBUÍDAS


TEMA 04 – CONTINUAÇÃO DA PROGRAMAÇÃO CONCORRENTE

TEXTO PARA APOIO AO ESTUDO

1) Introdução

Java suporta a programação multithreading, o que significa que os programas


multithreading podem conter dois ou mais trechos de códigos que podem ser executados
separadamente, lidando com tarefas diferentes ao mesmo tempo, otimizando o uso dos
recursos disponíveis, especialmente em computadores que têm processadores com vários
núcleos.

O conceito de multitarefa é utilizado quando múltiplos processos compartilham


recursos de processamento comuns como a CPU. Entretanto, o conceito de multithreading
amplia o conceito de multitarefa, de modo que as aplicações possam subdividir operações
específicas em threads individuais, que podem ser executadas em paralelo. Os Sistemas
Operacionais não dividem o tempo de processamento apenas entre as aplicações diferentes
mas, também, entre cada thread das aplicações.

As aplicações desenvolvidas com Java são executadas por meio de threads, que são caminhos
diferentes de execução do código do programa. Quando várias threads estão executando, o
caminho de uma thread pode ser diferente do caminho de outra thread.

Vamos considerar, por exemplo, a estrutura switch/case, sendo que threads diferentes
podem lidar com cada um dos cases.

Toda aplicação Java tem uma thread padrão que executa o método main(). A aplicação
também pode criar threads que lidam com tarefas que demandem maior poderio
computacional (como recursos de processamento e memória) executando em segundo plano,
de modo que seja possível outros processamentos possam ser realizados como, por exemplo,
responder aos acionamentos do mouse, do teclado, etc. Essas threads executam sequências de
códigos encapsuladas em objetos que são denominados runnables.

A JVM fornece a cada thread sua própria pilha JVM para evitar que haja interferências
entre threads diferentes. Esta abordagem de pilhas separadas permite que as threads
acompanhem a próxima instrução a ser executada, que pode diferir de uma para outra thread.
É possível lidar com threads em Java de duas formas diferentes:

• Classe java.lang.Thread;
• Interface java.lang.Runnable.
2) Ciclo de vida de uma thread

Uma trhead passa por diferentes estágios durante a sua existência. Usaremos os termos
em Inglês objetivando facilitar o entendimento das funções que serão estudadas
posteriormente. A Figura 1 ilustra o ciclo de vida das threads.

Figura 1 – Ciclo de vida das threads.

Descrevendo textualmente, os estágios do ciclo de vida das threads são os seguintes:

• New: uma nova thread é gerada e começa o seu ciclo de vida. Ela permanece neste
estágio até que o programa inicie-a pelo método start();
• Runnable: depois que uma thread foi criada e inicializada, ela é considerada executável
(Runnable);
• Running: depois que uma thread entra no estado executável, é possível utilizar o
método run() para, de fato, executá-la, de modo que ela realize o processamento que
foi designada a fazer;
• Waiting: objetivando a sincronização dos processamentos das threads,
frequentemente, é necessário utilizar recursos que possam atrasar a continuidade do
processamento das threads, de modo que elas possam esperar que outras threads
realizem seus processamentos antes que ela continue o seu. Por meio dos métodos
sleep() e wait(), podemos estabelecer a sincronização.
• Dead: quando a thread é finalizada.

3) Prioridades das threads

Cada thread em Java tem uma prioridade que ajuda o Sistema Operacional a determinar
a ordem na qual as threads serão executadas.

As prioridades de threads em Java variam de MIN_PRIORITY (valor 1) até MAX_PRIORITY


(valor 10). Por padrão, cada thread é atribuída à prioridade NORM_PRIORITY (valor 5).

Threads com altas prioridades são mais importantes para um programa e devem ser
alocados tempos de processamento para que elas sejam executadas antes das threads com
menores níveis de prioridades. Entretanto, é importante atentar para qualquer alteração que se
considere fazer nos níveis de prioridade porque eventuais erros podem comprometer o
processamento.
4) Utilização de threads por meio da interface Runnable

Se uma determinada classe precisa ser executada como uma thread, então podemos
implementar por meio da interface Runnable.

Inicialmente, precisamos executar o método run() fornecido pela interface Runnable.


Este método run() fornece um ponto de entrada para a thread e digitaremos, dentro deste
método, as linhas de código que desejamos executar. A sintaxe deste método está mostrado a
seguir:

Em seguida, instanciaremos um objeto do tipo Thread, usando o construtor mostrado a


seguir:

Sendo que threadObj é a instância de uma classe que implementa a interface Runnable.
E threadName é o nome dado para a nova thread.

Uma vez que o objeto Thread é criado, pode-se inicializa-lo por meio da invocação do
método start() que, por sua vez, executa a chamada para o método run().

Vamos ver agora um exemplo completo, que utiliza as funções descritas acima.
A saída do programa será:
5) Utilização de threads por meio da classe Thread

Outra possibilidade de criação de threads é por meio da classe Thread. A princípio, é


preciso sobrescrever o método run(), que está disponível na classe Thread. De modo semelhante
ao caso anterior, este método também fornece um ponto de entrada para thread e
escreveremos nosso código dentro deste método.

Ainda de forma semelhante ao caso anterior, uma vez que um objeto Thread é
instanciado, ele é iniciado por meio do método start(), que chama o método run().

Vamos ver também um exemplo completo:


E a saída do programa será:
A classe Thread tem funcionalidades que possibilitam a utilização dos recursos
necessários do Sistema Operacional que, normalmente, possibilitam a criação e gerenciamento
de threads.

A interface Runnable tem o código necessário para ser executados pela thread que está
associada com um objeto Thread. Este código está localizado no método run() de Runnable.

Com exceção da thread associada ao método main(), as threads são introduzidas por
meio dos objetos Thread e Runnable. Thread declara vários construtores para a inicialização de
objetos Thread. E vários destes construtores requerem um objeto Runnable como argumento.

Há duas maneiras de se criar um objeto Runnable. A primeira delas considera a criação


de uma classe anônima que implementa Runnable, conforme mostrado a seguir:

No código acima, é criado o objeto r, que é do tipo Runnable.

Ants do Java 8, esta era a única maneira de criar um runnable. Porém, Java 8 introduziu
a denominada expressão lambda, que permite que se crie runnable de forma mais simplificada,
conforme mostrado a seguir:

Depois da criação do objeto Runnable (r), pode-se passa-lo como parâmetro de entrada
do construtor Thread que recebe um argumento do tipo Runnale, conforme mostrado no
fragmento de código abaixo:

O código acima criou então um objeto t, que é do tipo Thread, a partir de um objeto r,
do tipo Runnable.

Mas alguns construtores podem não utilizar argumentos do tipo Runnable e, nestes
casos, é necessário sobrescrever seu método run() para possibilitar a execução do código,
conforme mostra o fragmento de código abaixo:

Você também pode gostar