aula sobre multithreading
DESCRIPTION
Slides da aula sobre programação usando múltiplas threads em Java.TRANSCRIPT
![Page 1: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/1.jpg)
Linguagem de Programação III
Multithreading
Professora: Bianca de Almeida Dantas
E-mail: [email protected]
Site: www.biancadantas.com
![Page 2: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/2.jpg)
TÓPICOS
• Threads
• Ciclo de vida
• Agendamento
• Criação e execução
• Exemplo
• Produtor-Consumidor
• Multithreading com GUI
Essa aula e seus exemplos foram baseados no
capítulo 26 do livro Java - Como Programar, 8ª
Edição (Deitel & Deitel)
![Page 3: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/3.jpg)
THREADS
• Linhas de execução dentro de um processo. Conhecidas como processos leves.
• Cada thread possui sua pilha de chamadas de métodos e contador de instruções, entretanto a troca de contexto entre threads de um mesmo processo é menos custosa.
• Permite a execução concorrente de trechos de código que independem entre si.
• Se mais de um núcleo de processamento estiver disponível, a execução pode ser paralela.
![Page 4: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/4.jpg)
• Linhas de execução dentro de um processo. Conhecidas como processos leves.
• Cada thread possui sua pilha de chamadas de métodos e contador de instruções, entretanto a troca de contexto entre threads de um mesmo processo é menos custosa.
• Permite a execução concorrente de trechos de código que independem entre si.
• Se mais de um núcleo de processamento estiver disponível, a execução pode ser paralela.
![Page 5: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/5.jpg)
• Linhas de execução dentro de um processo. Conhecidas como processos leves.
• Cada thread possui sua pilha de chamadas de métodos e contador de instruções, entretanto a troca de contexto entre threads de um mesmo processo é menos custosa.
• Permite a execução concorrente de trechos de código que independem entre si.
• Se mais de um núcleo de processamento estiver disponível, a execução pode ser paralela.
![Page 6: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/6.jpg)
THREADS – Ciclo de Vida
![Page 7: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/7.jpg)
• Novo: a thread acaba de ser criada e ainda não foi iniciada pela primeira vez.
• Executável: a thread está realizando o seu processamento ou pronta para executá-lo.
• Espera: a thread está esperando que outra thread realize uma tarefa. Volta para o estado executável apenas quando outra thread a notifica.
• Espera sincronizada: a thread está esperando por um intervalo máximo de tempo.
![Page 8: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/8.jpg)
• Bloqueado: a thread tentou realizar uma tarefa que não pôde ser imediatamente completada, ela fica neste estado até que a tarefa seja completada e, então, transita para o estado executável.
• Terminado: uma thread entra neste estado quando finaliza seu processamento (com ou sem sucesso).
![Page 9: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/9.jpg)
• O estado executável pode ser subdividido em dois estados separados operacionalmente: pronto e em execução.
• O SO oculta a diferença entre esses dois estados da JVM, que os vê unicamente como executáveis.
• Quando uma thread é criada e passa para o estado executável, ela está, na verdade, no estado pronto; quando ela está efetivamente executando, ela está no estado em execução.
![Page 10: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/10.jpg)
• Despachar uma thread: quando uma thread tem um processador atribuído a ela.
• Geralmente, uma thread executa por um pequeno período de tempo, o chamado quantum ou fração de tempo.
• Quando o quantum termina, a thread passa novamente para o estado pronto.
![Page 11: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/11.jpg)
![Page 12: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/12.jpg)
• Agendamento de threads é o processo que o sistema operacional utiliza para definir a ordem de execução de threads.
• O agendador de threads (thread scheduler), em geral, utiliza as prioridades associadas às threads para definir sua política de execução.
• Em Java, as prioridades variam entre MIN_PRIORITY (uma constante de 1) e MAX_PRIORITY (uma constante de 10). Threads, geralmente, são iniciadas com NORM_PRIORITY.
• As três constantes são definidas na classe Thread.
THREADS – Agendamento
![Page 13: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/13.jpg)
.......
![Page 14: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/14.jpg)
• Para especificar uma classe cujo código pode ser executado concorrentemente em uma aplicação, pode-se utilizar a interface Runnable.
• As threads podem ser instanciadas passando como argumento um objeto Runnable.
THREADS – Criação e Execução
![Page 15: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/15.jpg)
EXEMPLO • Código do projeto Multithread2 enviado por e-
mail....
![Page 16: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/16.jpg)
pool-1-thread-1 escreveu o valor 1 em 0
Próximo índice = 1
pool-1-thread-2 escreveu o valor 11 em 0
Próximo índice = 2
pool-1-thread-1 escreveu o valor 2 em 1
Próximo índice = 3
pool-1-thread-2 escreveu o valor 12 em 2
Próximo índice = 4
pool-1-thread-1 escreveu o valor 3 em 3
Próximo índice = 5
pool-1-thread-2 escreveu o valor 13 em 4
Próximo índice = 6
Conteúdo do vetor:
[11, 2, 12, 3, 13, 0]
![Page 17: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/17.jpg)
• Como as threads executam independentemente e compartilham um vetor, o resultado pode não ser como desejado.
• Pela saída anterior, vimos que a thread 2 sobrescreveu o valor recém escrito pela thread 1.
• Situações como essa, nas quais não conseguimos garantir que o resultado será coerente e nas quais o resultado dependerá da ordem em que as threads serão escalonadas são chamadas de condições de corrida.
![Page 18: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/18.jpg)
• O trecho de código no qual as diferentes threads acessam as variáveis compartilhadas (possivelmente, modificando-as) é chamado de seção crítica.
• Resumindo: o código visto não é seguro para threads.
• Para resolver o problema, transformaremos os trechos de acesso às variáveis compartilhadas em operações atômicas, impedindo que mais de uma thread execute tais instruções simultaneamente.
![Page 19: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/19.jpg)
EXEMPLO • Código do projeto Multithread2 alterado enviado
por e-mail.
• Nesse código, fizemos com que o código do método que adiciona um elemento ao SimpleArray seja atômico. Em Java, isso é feito usando a palavra-chave synchronized.
• Quando uma thread está executando o corpo de um método synchronized, nenhuma outra pode executá-la antes da primeira terminar sua execução.
• A instrução synchronized também pode ser utilizada para trechos de código.
![Page 20: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/20.jpg)
PRODUTOR-CONSUMIDOR • Um problema clássico da computação que envolve
processos (ou threads) que produzem recursos para serem consumidos por outros.
• Existe um buffer compartilhado para armazenamento dos recursos. O produtor precisa parar de produzir quando o buffer estiver cheio e o consumidor não pode consumir se não houver recurso disponível.
![Page 21: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/21.jpg)
ABORDAGEM 1
• Utilizar um buffer compartilhado com apenas uma posição (classe BufferSemSincronizacao).
• Não há garantia sobre a ordem de execução das threads, logo, muitas vezes valores são produzidos com o buffer lotado ou, ainda, consumidos antes da produção, levando a resultados inconsistentes.
![Page 22: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/22.jpg)
ABORDAGEM 2 • Utilizar um buffer compartilhado com apenas uma
posição, mas utilizando ArrayBlockingQueue (classe BufferBloqueante).
• A classe ArrayBlockingQueue pertence ao pacote java.util.concurrent, segura para threads e que implementa a interface BlockingQueue (que estende a classe Queue) e declara os métodos put e take (equivalentes bloqueantes dos métodos offer e poll.
• put coloca um elemento no fim da fila bloqueando se a mesma estiver cheia.
![Page 23: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/23.jpg)
• take retira um elemento do começo da fila bloqueando se a mesma estiver vazia.
• O tamanho do ArrayBlockingQueue é passado como argumento para o construtor e não é aumentado dinamicamente.
![Page 24: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/24.jpg)
ABORDAGEM 3 • Utilizar um buffer compartilhado com apenas uma
posição, mas utilizando métodos sincronizados (synchronized).
• Utiliza uma variável booleana ocupado que indica se o buffer está totalmente ocupado ou não.
• O produtor espera enquanto o buffer estiver lotado utilizando uma chamada ao método wait. Similarmente, o consumidor espera enquanto o buffer estiver vazio.
• O método wait faz com que o objeto que o executou libere implicitamente o bloqueio sobre o buffer.
![Page 25: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/25.jpg)
• O produtor/consumidor só é liberado de sua espera quando for notificado de que o objeto compartilhado já foi utilizado; isso é feito com a chamada a notifyAll.
• O método notifyAll retira do estado de espera todas as threads que estiverem esperando pelo objeto compartilhado, fazendo com que elas passem ao estado executável e tentem readquirir o bloqueio.
![Page 26: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/26.jpg)
ABORDAGEM 4 • Utilizar um buffer circular compartilhado com 4
posições.
• Permite minimizar o tempo de espera das threads devido ao aumento das posições disponíveis para escrita e leitura.
• Utiliza:
• uma variável auxiliar para controlar quantos elementos válidos realmente há no buffer em um determinado momento.
• Dois índices para indicar onde será feita a próxima leitura ou a próxima escrita.
![Page 27: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/27.jpg)
MULTITHREADING COM GUI • Aplicativos GUI são desafiantes para programação
multithreaded.
• Aplicativos swing possuem uma única thread, a thread de despacho de eventos, responsável por tratar as interações com os componentes GUI do aplicativo.
• Todas as tarefas que exigem interação com a GUI do aplicativo são colocadas em uma fila de eventos e executadas em sequência pela thread de despacho de eventos.
![Page 28: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/28.jpg)
• Componentes GUI Swing não são seguros para threads.
• Segurança para threads em aplicativos GUI é obtida assegurando que os componentes Swing são acessado a partir de uma única thread (a de despacho de eventos). Essa técnica é chamada de confinamento de thread.
• Utilizando essa ideia, uma alternativa interessante é colocar as atividades de longa duração, que independem da interface enquanto são executadas, em threads separadas da de despacho de eventos.
![Page 29: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/29.jpg)
• Essa alternativa evita que a thread de despacho de eventos fique sem responder enquanto espera pelo resultado de tais atividades.
• Para auxiliar na programação dessas atividades mais demoradas em threads separadas, o Java SE 6 fornece a classe SwingWorker. Essa classe pode realizar cálculos demorados e, então, atualizar s componentes Swing a partir da thread de despacho de eventos com base nos resultados dos cálculos.
• SwingWorker implemente a interface Runnable.
![Page 30: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/30.jpg)
• Métodos comuns de SwingWorker:
• doInBackground: define o cálculo longo na thread trabalhadora;
• done: executado na thread de despacho de eventos quando doInBackground retorna;
• execute: agenda o objeto SwingWorker a ser executado em uma thread trabalhadora;
• get: espera a conclusão do cálculo e retorna o seu resultado;
• publish: envia resultados intermediários dos cálculos para processamento na thread de despacho de eventos.
![Page 31: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/31.jpg)
• process: recebe os resultados intermediários e os processa na thread de despacho de eventos;
• setProgress: configura a propriedade de progresso para notificar os ouvintes de alteração de propriedade na thread de despacho de eventos de atualizações da barra de progresso.
![Page 32: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/32.jpg)
EXEMPLO 1: FIBONACCI • No exemplo, forneceremos uma opção para calcular os
termos da sequência de Fibonacci um a um ou para calcular um termo específico (até o 92º) em uma thread trabalhadora.
• SwingWorker é uma classe genérica que recebe dois parâmetros: o primeiro é o tipo retornado pelo método doInBackground e o segundo é o tipo passado entre os métodos publish e process.
![Page 33: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/33.jpg)
EXEMPLO 2: ÍMPARES • No exemplo, calculamos todos os números ímpares
menores que um valor inteiro fornecido como entrada.
• Para obtenção dos ímpares, utilizamos o crivo de Eratóstenes.
• Os resultados são exibidos em uma área de texto à medida em que são obtidos.
• Uma barra de progresso mostra o quanto do cálculo já foi concluído até um determinado momento.
![Page 34: Aula sobre multithreading](https://reader033.vdocuments.site/reader033/viewer/2022052620/5572c7dfd8b42abb378b4ba0/html5/thumbnails/34.jpg)
REFERÊNCIAS
• Java Como Programar – 8ª Edição. Deitel & Deitel.