0% acharam este documento útil (0 voto)
111 visualizações25 páginas

2-Concorrência e Paralelismo

O documento discute conceitos de concorrência e paralelismo, incluindo threads e a classe Thread no Java. É explicado que threads permitem a execução simultânea de tarefas dentro de um processo compartilhando memória.

Enviado por

Lucas Albertini
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
111 visualizações25 páginas

2-Concorrência e Paralelismo

O documento discute conceitos de concorrência e paralelismo, incluindo threads e a classe Thread no Java. É explicado que threads permitem a execução simultânea de tarefas dentro de um processo compartilhando memória.

Enviado por

Lucas Albertini
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 25

Linguagem de Programação II

Aula 2
Concorrência e Paralelismo

l.bertholdo@ifsp.edu.br
Conteúdo
• Conceitos sobre Concorrência e Paralelismo

• Threads

• Classe Thread

• Interface Runnable

l.bertholdo@ifsp.edu.br
Conceitos sobre Concorrência e Paralelismo
• Sistemas Monotarefa e Multitarefa
• Os primeiros sistemas operacionais suportavam a execução de
apenas uma tarefa por vez. Nesse modelo, o processador e a
memória ficavam dedicados a uma única tarefa.
• Somente após o término da execução de uma tarefa que outra
poderia ser carregada na memória e então executada.

Início Em Execução Fim

• O problema deste modelo é que Imagine um editor de texto que


enquanto a tarefa realizava uma precisa distribuir as palavras em
operação de I/O para, por exemplo, cada linha e verificar a ortografia ao
mesmo tempo, enquanto o usuário
ler dados do disco, o processador digita o texto. Em um sistema
ficava ocioso. monotarefa isso não seria possível.
l.bertholdo@ifsp.edu.br
Conceitos sobre Concorrência e Paralelismo
• A solução para este problema foi permitir ao processador suspender a
execução de uma tarefa, que estivesse aguardando dados externos ou
algum outro evento, e passar a executar outra tarefa.
• Após a obtenção dos dados ou o término do evento, a tarefa suspensa
seria então retomada. Note que nesse modelo, mais de uma tarefa
pode ser carregada na memória.
• O mecanismo que permite alternar a execução de uma tarefa em um
dado recurso (como o processador, por exemplo) para a execução de
outra tarefa no mesmo recurso é chamado de preempção.
A constante alternância entre as tarefas em execução faz com que a preempção seja
um processo custoso para o sistema operacional. Apesar disso, sistemas preemptivos
são mais produtivos, pois várias tarefas podem estar em execução no mesmo intervalo
de tempo, intercalando entre si o uso dos recursos da forma mais otimizada possível.
l.bertholdo@ifsp.edu.br
Conceitos sobre Concorrência e Paralelismo
• Estados de uma tarefa em um sistema preemptivo:
A tarefa está em memória aguardando a
disponibilidade do processador para ser executada
A tarefa está sendo (pela primeira vez ou para ser retomada). O processador está
carregada na memória. executando a tarefa.
quantum*

Nova Pronta Em Execução Finalizada

A tarefa está temporariamente


suspensa por depender de dados Suspensa A execução da tarefa
externos ainda não disponíveis, está finalizada e ela é
ou de algum outro evento. removida da memória.

*quantum é o tempo que o sistema operacional disponibiliza para que uma tarefa use o processador.
Quando o quantum de uma tarefa termina, mesmo que ela ainda não tenha terminado, seu contexto é
salvo na sua pilha de execução onde ela parou, e então ela volta para o estado “Pronta”. Quando o
escalonador de processos do sistema operacional disponibilizar novamente o processador para a tarefa,
ela volta então para o estado “Em Execução”. O escalonador é responsável por cuidar dessa fila de
tarefas e decidir quem tem prioridade, intercalando as tarefas para que o processador não fique ocioso.
l.bertholdo@ifsp.edu.br
Conceitos sobre Concorrência e Paralelismo
• Processos e Threads
• Um processo pode ser visto como um container de recursos
(processador, memória etc) utilizados por uma ou mais tarefas.
• Como os recursos são atribuídos aos processos, as tarefas de um
processo compartilham memória entre si. Porém, uma tarefa de
um processo A não consegue usar um recurso do processo B, ou
seja, processos não compartilham suas memórias.
As tarefas de um mesmo processo podem trocar informações facilmente, pois compartilham a mesma
área de memória. Porém, tarefas de processos distintos só conseguem se comunicar com chamadas de
sistema do kernel*, que permitem a comunicação entre processos (IPC - Inter-Process Communication).

• As tarefas de um processo são definidas por threads (ou linhas de


execução) dentro de um processo, as quais compartilham entre si a
memória atribuída ao processo.
* kernel: Núcleo do sistema operacional responsável pela comunicação entre o hardware e o softwarel.bertholdo@ifsp.edu.br
de um computador.
Conceitos sobre Concorrência e Paralelismo
• Concorrência
• Consiste na execução intercalada de um conjunto de tarefas em
um dado intervalo de tempo.
• Em um sistema operacional, é o escalonador de processos que
gerencia a concorrência, pausando e retomando tarefas até que
todas sejam completamente executadas.

No contexto de um sistema operacional, concorrência é como uma fila de


drive thru em que carros estão disputando, um por vez, o “recurso” do
atendimento. Porém, é um drive thru diferente, porque os carros possuem um
tempo máximo em que podem ficar no atendimento. Passado este tempo, o
carro precisa voltar para a fila para dar oportunidade ao próximo carro da fila.

Concorrência é sobre lidar com várias coisas em um mesmo intervalo de tempo. Paralelismo
é sobre fazer várias coisas ao mesmo tempo. (Rob Pike, um dos criadores da linguagem Go)
l.bertholdo@ifsp.edu.br
Conceitos sobre Concorrência e Paralelismo
• Paralelismo
• Consiste na execução simultânea de tarefas.
Paralelismo é como um pedágio que permite que carros
avancem em diferentes fluxos simultaneamente.

• A quantidade de tarefas paralelas possíveis depende da quantidade


de núcleos (cores) do processador.
Processo
• Do ponto de vista de um processador com Thread 0 Thread 1 Thread 2
três núcleos, um processo poderia ter, por
exemplo, três threads rodando simultânea- CPU CPU CPU
(core 1) (core 2) (core 0)
mente, uma em cada núcleo.
Paralelismo implica concorrência, pois cada thread paralela também é concorrente, já que os
poucos núcleos estarão sendo disputados por muitas threads. Inclusive, quem gerencia qual
thread cada núcleo vai executar em dado momento é também o escalonador de processos.
l.bertholdo@ifsp.edu.br
____________
____________

Threads ____________
____________
____________
____________
____________
____________

• Uma thread é um fluxo sequencial de execução dentro de


____________
____________
____________
____________
um programa ou de um contexto de execução, que envolve ____________
____________
____________
memória, processador, software e outros recursos. ____________
____________

• Cada thread executa um conjunto definido de instruções do programa.


Porém, num dado momento, o processamento do programa pode
ocorrer simultaneamente em diversas frentes, uma para cada thread
ativa, definindo fluxos independentes para tarefas específicas.
• Aplicações que implementam threads com um único fluxo de execução
são denominadas single-threaded. Já aquelas que permitem múltiplos
fluxos simultâneos são chamados de multithreaded.
O emprego das threads pode tornar um programa mais eficiente em várias situações.
Elas podem ser usadas, por exemplo, para garantir que a interface fique disponível
para o usuário, enquanto a aplicação executa uma tarefa em segundo plano.
l.bertholdo@ifsp.edu.br
Threads
• O uso de threads requer cuidados, como estabelecer a divisão do
trabalho em tarefas menores que possam ser executadas em paralelo e
cujo processamento não apresente dependências entre si.

Se os parâmetros de entradas para realização de um cálculo dependerem de cálculos


anteriores, então esses cáculos deverão ser executados sequencialmente.
Se um recurso do sistema (arquivo, dispositivo ou outros) for acessado para escrita por
várias threads, será necessário sincronizar essas operações para evitar a corrupção
dos dados, ou seja, fazer com que o recurso seja usado por uma thread de cada vez.

• A execução das threads é conduzida pelo sistema operacional. Dessa


forma, um mesmo programa apresentará comportamentos diferentes
dependendo de como a plataforma trata as suas threads, o que exige
avaliações e testes cuidadosos durante sua implementação.
• Existem duas formas básicas para trabalhar com threads em Java:
por meio da classe Thread e da interface Runnable.
l.bertholdo@ifsp.edu.br
Classe Thread
• A classe Thread pertence ao pacote java.lang e representa um fluxo
independente de execução dentro de um programa.
• Em geral, novas threads são definidas pela criação de subclasses de
Thread, nas quais se implementa o método run, que deve conter o
código a ser executado.
Essa thread imprime a contagem de 1 até 3,
acompanhada do próprio nome da thread.
No início e fim de cada thread, são impressas
mensagens indicativas: Início e Fim.

l.bertholdo@ifsp.edu.br
Classe Thread
• A criação de uma thread envolve a instanciação (por meio do
operador new) da classe que implementa a thread.
• Para colocar uma thread em execução, é preciso iniciá-la com uma
chamada ao método start, que solicita o escalonamento da thread
para o sistema operacional e a consequente execução do método run.
• A aplicação abaixo instancia e executa três threads idênticas
utilizando a classe ExemploThread:

É possível definir um nome para uma


thread por meio do construtor da classe
thread, ou do método setName, mas se
isso não for feito, será atribuído o nome
padrão “Thread-X’, onde “X’ é um
número sequencial iniciado em zero.

l.bertholdo@ifsp.edu.br
Classe Thread
• Resultado da execução da classe
TestaThreads:

Outras execuções do mesmo programa poderão


exibir resultados diferentes, refletindo mais o estado
do contexto de execução do que da aplicação em si.

O resultado mostra as mensagens indicativas de início e fim do teste, bem como as mensagens das
threads (Thread-0, Thread-1 e Thread-2). Mesmo após o final do método main, a execução continua, pois
as três threads ainda não terminaram seu processamento. Note que as mensagens de início, contagem e
fim das threads se misturam, evidenciando sua execução em paralelo e sem qualquer sincronização.
l.bertholdo@ifsp.edu.br
Classe Thread
• Alguns dos principais métodos da classe Thread:
Método Descrição
Thread currentThread() Retorna uma referência para a thread em execução.
String getName(), Obtém ou define o nome da thread.
void setName(String nome)
int getPriority(), Obtém ou define a prioridade da thread por meio das constantes: MAX_PRIORITY,
void setPriority(int prioridade) MIN_PRIORITY e NORMAL_PRIORITY. Por exemplo: t1.setPriority(Thread.MAX_PRIORITY);
void interrupt() Interrompe a execução da thread.
boolean isAlive(), Determina se a thread está em execução, se é um daemon ou se foi interrompida. Obs.:
boolean isDaemon(), Threads daemon (ou threads de serviço) são aquelas que prestam serviços para outras
boolean islnterrupted() threads, enquanto as threads de usuário são todas as demais.
void join(), void join(long millis) Define uma espera para finalização da thread, opcionalmente pelo tempo indicado.
void run() Método que contém o código que será executado pela thread.
void setDaemon(boolean on) Marca a thread como um daemon.
void sleep(long millis) Suspende a thread corrente pelo número de milissegundos indicado.
void start() Inicia a execução da thread.
void yield() Indica para o escalonador que a thread está disposta a ceder o uso do processador.

• Mais detalhes sobre a classe Thread podem ser encontrados em:


https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/lang/Thread.html
l.bertholdo@ifsp.edu.br
Classe Thread – Exemplo
• Para exemplificar o uso de threads, serão A classe PrimosST (sem thread) usa
apresentadas duas aplicações que retornam a classe Painel para gerar sua
interface e efetuar o cálculo dos
os números primos em um dado intervalo. números primos na mesma thread
• A classe Painel cria uma pequena janela desta interface. A classe PrimosCT
(com thread) tem o mesmo
contendo todos os componentes de comportamento, porém implementa
interface necessários para as aplicações. sua própria thread para o cálculo.

l.bertholdo@ifsp.edu.br
Classe Thread – Exemplo
• Classe PrimosST (sem thread)

Continuação

l.bertholdo@ifsp.edu.br
Classe Thread – Exemplo
• Ao executar o cálculo para grandes intervalos (por ex.: 1 a 200.000),
a classe PrimosST apresenta um comportamento inadequado:
• Os botões Executar e Limpar não são desabilitados, e o botão Executar fica
com aparência de “travado” durante o processamento.
• Os botões Cancelar e Limpar dão a impressão de que não funcionam
durante o processamento. O mesmo ocorre com os botões para
redimensionar e fechar a janela.
• Os resultados são apresentados somente ao final do processamento.
Aplicação PrimosST durante o processamento

Esses problemas ocorrem porque a rotina de cálculo é


executada na mesma thread em que ocorre o processamento
de eventos da interface. Como resultado, tais eventos são
executados e/ou renderizados somente após o final do cálculo.

Note que mesmo as modificações na interface solicitadas antes da chamada do cálculo, como a
desabilitação dos botões Limpar e Executar, são renderizadas de fato somente após o cálculo. l.bertholdo@ifsp.edu.br
Classe Thread – Exemplo
• Classe PrimosCT (com thread)
Continuação

A variável de controle cancel verifica, a cada laço do for, se o


usuário clicou no botão Cancelar (cancel == true). Na classe
PrimosST, como a interface e o cálculo estão na mesma thread,
uma mudança no estado desta variável só tem efeito após a
execução do for, o que torna ela sem utilidade. Já na classe
PrimosCT esta variável faz sentido, pois a interface e o cálculo estão
sendo processados em threads diferentes. Com isso, uma mudança
no estado desta variável tem efeito durante a execução do for.
l.bertholdo@ifsp.edu.br
Classe Thread – Exemplo
• A classe PrimosCT corrigiu o comportamento da classe PrimosST.
• Em vez de acionar o cálculo no método de tratamento de eventos
actionPerformed, a classe PrimosCT instancia uma thread da classe
interna Calculo.
• O método run desta classe interna aciona o cálculo, separando seu
processamento em outra thread, enquanto o tratamento de eventos
da interface segue utilizando sua thread padrão.
• Com isso a aplicação passa a ter comportamento adequado, mesmo
para grandes intervalos, eliminado os problemas mencionados na
classe PrimosST.

Aplicação PrimosCT durante


o processamento

l.bertholdo@ifsp.edu.br
Classe Thread – Exemplo
• Classe PrimosCT2 (com thread) – Classe anônima e Expressão lambda
Podemos simplificar o código da classe PrimosCT
com o uso de classes anônimas e expressões
lambda, eliminando a necessidade de criar a classe
interna Calculo. O código destacado no método
actionPerformed retorna uma instância de uma
classe anônima que implementa o método run da
interface Runnable. No caso, esta implementação é
o próprio código da thread a ser executada. Essa
mesma estratégia é usada no método main.

Continuação

l.bertholdo@ifsp.edu.br
Classe Thread – Exemplo
• Classe anônima é uma classe interna sem nome, que é subclasse de
outra classe ou implementa uma interface, e tem a função de
instanciar um único objeto. Seu objetivo é evitar a declaração de uma
classe apenas para atender uma necessidade pontual no código.

• Expressão lambda é um método sem declaração (sem assinatura),


que pode ser usado como parâmetro de entrada na chamada de
outro método, ou como valor de retorno de outro método.

• A ideia é que o método seja declarado no mesmo lugar em que será


chamado. Em Java, um método lamdba tem a seguinte sintaxe:
([argumentos]) -> (código do método). Exemplo:

(int a, int b) -> { return a + b; }

l.bertholdo@ifsp.edu.br
Interface Runnable
• As threads também podem ser definidas por meio da interface
Runnable do pacote java.lang.

• Assim como na classe Thread, essa interface demanda a implementação


do método run, que conterá o código a ser executado pela thread.

• O uso explícito da interface Runnable é conveniente nas situações


em que a classe que define a thread não pode ser uma subclasse de
Thread, pois esta classe já estende outra classe.

• A interface Runnable também é útil quando o código da thread é


simples e conciso e pode ser facilmente expresso por meio de um
método lambda.

l.bertholdo@ifsp.edu.br
Interface Runnable
• A execução de threads criadas a partir da interface Runnable segue os
passos abaixo:
Passo Código de Exemplo
1. Definir a classe que implementa a interface Runnable public class Base implements Runnable {
e implementar o método run. @Override
public void run() {
// Código da thread
} }
2. Obter uma instância da classe que implementa a Base base = new Base();
interface Runnable.
3. Criar um objeto Thread por meio de um construtor // No método apropriado:
específico da classe Thread, o qual recebe como Thread thread1;
argumento uma referência do objeto Runnable. thread1 = new Thread(base, "base1");

4. Executar a thread por meio do objeto Thread criado. thread1.start();

• A aplicação a seguir exemplifica o uso da interface Runnable para a


definição de threads.
l.bertholdo@ifsp.edu.br
A classe PainelRelogio cria uma
Interface Runnable pequena janela destinada à exibição
de data e da hora atualizadas.

1. Define a classe que implementa a interface Runnable e


o comportamento da thread por meio do método run.

3. Cria um objeto Thread por meio do construtor da classe


Thread, o qual recebe uma referência do objeto Runnable.

2. Obtém uma instância da classe que


implementa a interface Runnable.
4. Executa a thread por meio
do objeto Thread criado.

Enquanto a thread em execução for a thread definida, o método


run é executado continuamente, com pausas de 1 segundo. O
resultado final é a exibição sempre atualizada da data e da hora.
A classe Relogio usa a classe Painel
Relogio para gerar sua interface e
exibir a data e hora atuais.
l.bertholdo@ifsp.edu.br
Referências
• Concorrência, Paralelismo, Processos, Threads, programação síncrona e
assíncrona. Disponível em: https://www.treinaweb.com.br/blog/
concorrencia-paralelismo-processos-threads-programacao-sincrona-e-
assincrona. Acesso em: 29 jan. 2024.

• Peter Jandl Junior; Java: Guia do Programador. 3ª Edição. São Paulo:


Novatec Editora, 2015.

l.bertholdo@ifsp.edu.br

Você também pode gostar

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy