Baixe o app para aproveitar ainda mais
Prévia do material em texto
1 Linguagens de Programacão I mleal@inf.puc-rio.br 1 Java ThreadsJava Threads Linguagens de Programacão I mleal@inf.puc-rio.br 2 IntroduçãoIntrodução O único mecanismo de concorrência O único mecanismo de concorrência suportado explicitamente pela linguagem suportado explicitamente pela linguagem Java é multiJava é multi--threading.threading. Os mecanismos de gerenciamento e Os mecanismos de gerenciamento e sicronização de threads foram incorporados sicronização de threads foram incorporados diretamente à linguagem (java.lang).diretamente à linguagem (java.lang). Um thread Java é representado por um Um thread Java é representado por um objeto da classe Thread (java.lang.Thread).objeto da classe Thread (java.lang.Thread). 2 Linguagens de Programacão I mleal@inf.puc-rio.br 3 IntroduçãoIntrodução QuandoQuando umauma aplicaçãoaplicação Java é Java é executadaexecutada:: A JVM A JVM criacria um um objeto objeto do do tipotipo Thread Thread cujacuja tarefatarefa a a ser ser executadaexecutada é é descritadescrita pelopelo métodométodo main()main().. O Thread é O Thread é iniciadoiniciado automaticamenteautomaticamente.. Os Os comandoscomandos descritosdescritos pelopelo métodométodo main() main() sãosão executadosexecutados sequencialmentesequencialmente atéaté queque o o métodométodo terminetermine e o thread e o thread acabeacabe.. Linguagens de Programacão I mleal@inf.puc-rio.br 4 Criando ThreadsCriando Threads Existem duas formas Existem duas formas de de criar explicitamentecriar explicitamente um um thread thread emem Java:Java: EstendendoEstendendo a a classeclasse ThreadThread e e instanciando instanciando um um objeto objeto desta desta nova nova classeclasse.. ImplementandoImplementando a interface a interface RunnableRunnable,,e e passando passando um um objeto desta objeto desta nova nova classe como argumento classe como argumento do do construtor da construtor da classeclasse ThreadThread.. Nos dois casos Nos dois casos a a tarefa tarefa a ser a ser executado pelo executado pelo thread thread deverá deverá ser ser descrita pelo métododescrita pelo método run()run().. 3 Linguagens de Programacão I mleal@inf.puc-rio.br 5 Exemplo Exemplo Estendendo Thread Estendendo Thread public class SimpleThread extends Thread {public class SimpleThread extends Thread { private String myName;private String myName; public SimpleThread(String str) { public SimpleThread(String str) { myName = str; myName = str; } } public void run() {public void run() { // Código executado pelo thread // Código executado pelo thread for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++) System.out.println(i + " " + myName; System.out.println(i + " " + myName; System.out.println("DONE! " + myName;System.out.println("DONE! " + myName; // fim// fim }} }} Linguagens de Programacão I mleal@inf.puc-rio.br 6 ExemploExemplo Estendendo ThreadEstendendo Thread Para Para iniciariniciar o thread é o thread é necessárionecessário instanciarinstanciar um um objetoobjeto dada nova nova classeclasse e e invocarinvocar o o métodométodo start()start() :: public class ThreadDemo {public class ThreadDemo { public static void main (String[] args) {public static void main (String[] args) { (new SimpleThread(“thread 1")).start();(new SimpleThread(“thread 1")).start(); (new SimpleThread(“thread 2")).start();(new SimpleThread(“thread 2")).start(); }} }} 4 Linguagens de Programacão I mleal@inf.puc-rio.br 7 A Interface RunnableA Interface Runnable Como Java não permite herança múltipla, a Como Java não permite herança múltipla, a necessidade de estender a classe Thread restringe a necessidade de estender a classe Thread restringe a criação de subclasses a partir de outras classes criação de subclasses a partir de outras classes genéricas.genéricas. Através da utilização da interface Runnable é Através da utilização da interface Runnable é possível criar classes que representem um thread possível criar classes que representem um thread sem precisar estender a classe Thread. Neste caso sem precisar estender a classe Thread. Neste caso podepode--se estender outras classes genéricas.se estender outras classes genéricas. A criação de um novo thread é feita através da A criação de um novo thread é feita através da instanciação de um objeto thread usando o objeto instanciação de um objeto thread usando o objeto que implementa a interface Runnable.que implementa a interface Runnable. Linguagens de Programacão I mleal@inf.puc-rio.br 8 Exemplo Exemplo Implementando RunnableImplementando Runnable class BasicThread2 implements Runnable{ class BasicThread2 implements Runnable{ // método que descreve o código a ser// método que descreve o código a ser // executado pelo thread// executado pelo thread public void run() {public void run() { ...... }} }} class Teste{class Teste{ public static void main(){public static void main(){ // Cria um objeto que possui um método run()// Cria um objeto que possui um método run() Runnable runnable = new BasicThread2(); Runnable runnable = new BasicThread2(); // Cria um novo thread usando um objeto runnable// Cria um novo thread usando um objeto runnable Thread thread = new Thread(runnable); Thread thread = new Thread(runnable); // inicia o thread// inicia o thread thread.start();thread.start(); ...... }} }} 5 Linguagens de Programacão I mleal@inf.puc-rio.br 9 Exemplo Exemplo Implementando RunnableImplementando Runnable public class Clock extends Applet implements Runnable {public class Clock extends Applet implements Runnable { private Thread clockThread = null;private Thread clockThread = null; public void start() {public void start() { if (clockThread == null) {if (clockThread == null) { clockThread = new Thread(this, "Clock");clockThread = new Thread(this, "Clock"); clockThread.start();clockThread.start(); }} }} public void run() {public void run() { Thread myThread = Thread.currentThread();Thread myThread = Thread.currentThread(); while (clockThread == myThread) {while (clockThread == myThread) { repaint();repaint(); try {try { Thread.sleep(1000);Thread.sleep(1000); } catch (InterruptedException e){}} catch (InterruptedException e){} }} }} ...... }} Linguagens de Programacão I mleal@inf.puc-rio.br 10 Controlando a ExecuçãoControlando a Execução start()start() Inicia Inicia a a execuexecuççãoão do threaddo thread ((ssóó pode pode ser ser invocado uma invocado uma vezvez).). yield()yield() Faz Faz com com que que a a execuexecuçção ão do thread do thread corrente seja corrente seja imediatamente suspensaimediatamente suspensa, e , e outro outro thread thread seja escalonadoseja escalonado.. sleep(t)sleep(t) Faz Faz com com que que o thread o thread fique suspenso por fique suspenso por t t segundossegundos.. wait()wait() FazFaz com com queque o thread o thread fiquefique suspensosuspenso atatéé queque seja seja explicitamenteexplicitamente reativado porreativado por um um outrooutro thread.thread. 6 Linguagens de Programacão I mleal@inf.puc-rio.br 11 Ciclo de Vida de um ThreadCiclo de Vida de um Thread Linguagens de Programacão I mleal@inf.puc-rio.br 12 Estado NonEstado Non--RunnableRunnable Um thread pode entrar no estado nonUm thread pode entrar no estado non-- runnable como resultado de:runnable como resultado de: a execução pelo thread de uma chamada de I/O a execução pelo thread de uma chamada de I/O bloqueante.bloqueante. a invocação explícita dos métodos sleep() ou a invocação explícita dos métodos sleep() ou wait() do objeto Thread.wait() do objeto Thread. O método yield() não torna o thread nonO método yield() não torna o thread non-- runnable, apenas transfere a execução para runnable, apenas transfere a execução para outro thread.outro thread. 7 Linguagensde Programacão I mleal@inf.puc-rio.br 13 EscalonamentoEscalonamento Mecanismo que determina como os threads irão Mecanismo que determina como os threads irão utilizar tempo de CPU.utilizar tempo de CPU. Somente os threads no estado runnable são Somente os threads no estado runnable são escalonados para ser executados.escalonados para ser executados. Java permite a atribuição de prioridades para os Java permite a atribuição de prioridades para os threads.threads. Threads com menor prioridade são escalonados com Threads com menor prioridade são escalonados com menor frequência.menor frequência. Os threads são escalonados de forma preempetiva Os threads são escalonados de forma preempetiva seguindo uma disciplina “round robin”.seguindo uma disciplina “round robin”. Linguagens de Programacão I mleal@inf.puc-rio.br 14 PrioridadesPrioridades Todo thread possui uma prioridade que:Todo thread possui uma prioridade que: pode ser alterada com pode ser alterada com setPriority(int p)setPriority(int p) pode ser lida com pode ser lida com getPriority()getPriority() Algumas constantes incluem:Algumas constantes incluem: Thread.MIN_PRIORITYThread.MIN_PRIORITY Thread.MAX_PRIORITYThread.MAX_PRIORITY Thread.NORM_PRIORITYThread.NORM_PRIORITY o padrão é o padrão é Thread.NORM_PRIORITYThread.NORM_PRIORITY 8 Linguagens de Programacão I mleal@inf.puc-rio.br 15 SincronizaçãoSincronização Cada thread possui uma pilha independente Cada thread possui uma pilha independente ÎÎ dois dois threads que executam o mesmo método possuem threads que executam o mesmo método possuem versões diferentes das variáveis locais.versões diferentes das variáveis locais. A memória dinâmica (heap) de um programa é A memória dinâmica (heap) de um programa é compartilhada por todos os threads compartilhada por todos os threads ÎÎ dois threads dois threads poderão portanto acessar os mesmos atributos de poderão portanto acessar os mesmos atributos de uma objeto de forma concorrente.uma objeto de forma concorrente. Devido ao mecanismo de preempção, não há como Devido ao mecanismo de preempção, não há como controlar o acesso a recursos compartilhados sem controlar o acesso a recursos compartilhados sem um mecanismo específico de sincronização.um mecanismo específico de sincronização. Linguagens de Programacão I mleal@inf.puc-rio.br 16 ExemploExemplo public class ContaCorrente {public class ContaCorrente { float saldo = 0;float saldo = 0; float tmp;float tmp; public float getSaldo(){public float getSaldo(){ return saldo;return saldo; }} public void depositar(float valor){public void depositar(float valor){ tmp = getSaldo();tmp = getSaldo(); saldo = tmp+valor;saldo = tmp+valor; }} public void sacar(float valor){public void sacar(float valor){ tmp = getSaldo();tmp = getSaldo(); saldo = tmpsaldo = tmp--valor;valor; } } }} 9 Linguagens de Programacão I mleal@inf.puc-rio.br 17 ExemploExemplo Thread 1 Thread 2 saldoThread 1 Thread 2 saldo ------ ------ 00 conta.depositar(100); conta.depositar(100); ------ 00 tmp = saldo; tmp = saldo; ------ 00 ------ conta.sacar(50); 0conta.sacar(50); 0 ------ tmp = conta; 0tmp = conta; 0 ------ saldo = tmp saldo = tmp -- 50; 50; --50 50 saldo = tmp + 100; saldo = tmp + 100; ------ 100100 0 Considere dois threads acessando uma mesma Considere dois threads acessando uma mesma conta simultaneamente, um invocando o método conta simultaneamente, um invocando o método depositardepositar e outro o método e outro o método sacarsacar.. Linguagens de Programacão I mleal@inf.puc-rio.br 18 SincronizaçãoSincronização Java pemite restringir o acesso a métodos de um Java pemite restringir o acesso a métodos de um objeto ou trechos de código através do modificador objeto ou trechos de código através do modificador synchronizedsynchronized.. Cada objeto Java possui um (e apenas um) lock.Cada objeto Java possui um (e apenas um) lock. Para invocar um método Para invocar um método synchronizedsynchronized é é necessário adquirir (implicitamente) o lock associado necessário adquirir (implicitamente) o lock associado ao objeto.ao objeto. Se dois ou mais métodos de um objeto forem Se dois ou mais métodos de um objeto forem declarados como declarados como synchronizedsynchronized, apenas um , apenas um poderá ser acessado de cada vez.poderá ser acessado de cada vez. 10 Linguagens de Programacão I mleal@inf.puc-rio.br 19 ExemploExemplo public class ContaCorrente {public class ContaCorrente { float saldo = 0;float saldo = 0; float tmp;float tmp; public float getSaldo(){public float getSaldo(){ return saldo;return saldo; }} public synchronized void public synchronized void depositar(float valor){depositar(float valor){ tmp = getSaldo();tmp = getSaldo(); Linguagens de Programacão I mleal@inf.puc-rio.br 20 wait() e notifyAll()wait() e notifyAll() O mecanismo de sincronização de Java é baseado O mecanismo de sincronização de Java é baseado em monitores, e utiliza uma variável condicional que em monitores, e utiliza uma variável condicional que é o próprio lock do objeto.é o próprio lock do objeto. As operações As operações wait(cond)wait(cond) e e signal(cond)signal(cond) usada usada em monitores são representadas em Java pelos em monitores são representadas em Java pelos métodos métodos wait()wait() e e notifyAll().notifyAll(). wait()wait() e e notifyAll()notifyAll()só podem ser usados só podem ser usados dentro de métodos ou trechos de código dentro de métodos ou trechos de código synchronized,synchronized, e não recebem parâmetros, já que e não recebem parâmetros, já que atuam sobre o lock do objeto.atuam sobre o lock do objeto. 11 Linguagens de Programacão I mleal@inf.puc-rio.br 21 wait() e notifyAll()wait() e notifyAll() Threads podem ser suspensos ao executarem o Threads podem ser suspensos ao executarem o comando wait().comando wait(). Ao ser suspenso dentro de um método Ao ser suspenso dentro de um método synchronized,synchronized, o thread libera imediatamente o o thread libera imediatamente o lock do objeto correspondente.lock do objeto correspondente. O thread suspenso só será reativado quando um O thread suspenso só será reativado quando um outro thread executar o comando notifyAll().outro thread executar o comando notifyAll(). Vários threads podem estar suspensos a espera do Vários threads podem estar suspensos a espera do lock de um objeto.lock de um objeto. Linguagens de Programacão I mleal@inf.puc-rio.br 22 ExemploExemplo class BlockingQueue extends Queue {class BlockingQueue extends Queue { public synchronized Object remove() {public synchronized Object remove() { while (isEmpty()) {while (isEmpty()) { wait(); // this.wait()wait(); // this.wait() }} return super.remove();return super.remove(); }} public synchronized void add(Object o) {public synchronized void add(Object o) { super.add(o);super.add(o); notifyAll(); // this.notifyAll()notifyAll(); // this.notifyAll() }} }}
Compartilhar