java aula 2 threads

68
Tecnologias Java Threads Marcio Seiji Oyamada [email protected] Pós-graduação Especialização em Desenvolvimento de Software e Novas Tecnologias

Upload: danylo-pereira

Post on 25-Sep-2015

29 views

Category:

Documents


3 download

DESCRIPTION

aula d e java

TRANSCRIPT

  • Tecnologias JavaThreads

    Marcio Seiji Oyamada

    [email protected]

    Especializao em Desenvolvimento de Software e Novas Tecnologias

  • Contedo programtico

    Apresentao da plataforma Java

    Threads

    Construo de ambientes grficos

    Acesso a base de dados

    Sockets

    RMI

    Applets

    Linguagem de script (JavaFX)

  • Threads

    nica linha de execuo x mltiplas linhas de execuo

  • Benefcios

    Tempo de resposta

    Compartilhamento de recursos

    Economia de recursos

    Desempenho em arquiteturas multiprocessadas

  • Muitos para um

    Vrias threads no nvel do usurio, mapeadas para uma nica thread no nvel do kernel

    Exemplos: Solaris Green Threads

    GNU Portable Threads

  • Um para um

    Cada thread no nvel do usurio mapeada para uma thread no nvel do kernel

    Exemplos Windows NT/XP/2000

    Linux

    Solaris 9 e verses posteriores

  • Threads em Java

    Gerenciada pela JVM Mapeamento para o sistema operacional depende

    da implementao da JVM

    Java Threads Classe Thread ou

    Interface Runnable

  • Interface Runnable

    Mtodo necessrio para descrever uma threadpublic interface java.lang.Runnable {

    // Methods

    public abstract void run();

    }

    Exemplo:class ThreadInterface implements Runnable{

    public void run(){

    for (int i=0; i

  • Classe Thread

    Classe principal que representa uma thread em Java

    Mtodos para gerenciar threads Obter nome da thread

    Alterar a prioridade

    Interromper uma thread

    Liberar o processador

  • Criando uma thread com a classe Thread

    public class ThreadClasse extends Thread {

    public ThreadClasse(){

    super();

    }

    public void run(){

    for (int i=0; i

  • Executando threads (Interface Runnable)

    Utilizando a interface Runnablepublic class ExecutaThread {

    public static void main(String args[]) throws

    InterruptedException{

    Thread t1;

    Thread t2;

    t1= new Thread(new ThreadInterface());

    t2= new Thread(new ThreadInterface());

    t1.start(); // inicia a execuo da Thread

    t2.start(); // inicia a execuo da Thread

    System.out.println(Thread inicializadas);

    t1.join(); // Aguarda a thread t1 finalizar

    t2.join(); // Aguarda a thread t1 finalizar

    System.out.println(Thread finalizadas);

    }

    }

  • Executando threads (Classe Thread)

    Utilizando a Classe Thread

    public class ExecutaThread {

    public static void main(String[] args) throws

    InterruptedException {

    // TODO code application logic here

    ClasseThread t1= new ClasseThread();

    ClasseThread t2= new ClasseThread();

    t1.start();

    t2.start();

    System.out.println("Thread inicializadas");

    t1.join();

    t2.join();

    System.out.println("Thread finalizadas");

    }

    }

  • Executors

    Gerencia um conjunto de Threads FixedThreadPool: nmero fixo de threads

    CachedThreadPool: aloca dinamicamente

    FixedThreadPool Evita o overhead com a criao de thread

    Maior controle dos recursos utilizados durante a execuo do sistema

  • Exemplo Executors (1)import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    public class Main {

    public static void main(String[] args) {

    // TODO code application logic here

    ExecutorService executor=

    Executors.newCachedThreadPool();

    for (int i=0; i < 5; i++){

    executor.execute(new ThreadInterface());

    }

    System.out.println("Threads executando");

    executor.shutdown();

    }

    }

  • Exemplo: Executors (2)

    public class ThreadInterface implements Runnable{

    public void run() {

    for (int i=0; i

  • Executors

    Mtodos Execute(Interface Runnable): submete uma nova

    interface para ser executada

    Shutdown(): previne que outras threads sejam submetidas ao ExecutorService

    ShutdownNow(): tentar finalizar a execuo das Threads

  • Interrompendo Threadspublic class MainInterruptTest {

    public static void main(String[] args) throws InterruptedException {

    ExecutorService executor= Executors.newCachedThreadPool();

    for (int i=0; i < 10; i++)

    executor.execute(new MyThread());

    System.out.println("Sleeping....");

    TimeUnit.SECONDS.sleep(10);

    executor.shutdownNow();

    System.out.println("Shutdown solicitado");

    }

    }

    class MyThread implements Runnable{

    public void run() {

    boolean sair=false;

    while (!sair){

    System.out.println(Thread.currentThread().getName());

    if (Thread.currentThread().isInterrupted()){

    System.out.println("Interrupo solicitada, finalizando a

    Thread"+ Thread.currentThread().getName());

    sair= true;

    }

    }

    }

    }

  • Thread.yield()

    Para a execuo da Thread atual e libera o processador para que uma outra Thread possa executar Forar a troca de contexto e conseqentemente uma melhor

    distribuio do processador

    public class ThreadInterface implements Runnable{

    public void run() {

    for (int i=0; i

  • Threads:Sleeppublic class SleepingTest implements Runnable {

    public void run() {

    try {

    for (int i=0; i

  • Inicializao de atributospublic class SleepingTest implements Runnable{

    boolean setYield= false;

    public SleepingTest (boolean _setYield){

    this.setYield= _setYield;

    }

    public void run() {

    for (int i=0; i

  • Exerccios

    1) Qual o comportamento na execuo das Threads utilizando o mtodo yield()?

    2) Faa uma aplicao multithread onde cada Thread escreva na tela N vezes uma String. O valor N e a String sero passados como parmetro pelo construtor

  • Threads: Retornando valores

    A interface Runnable no define um mtodo para retornar valores Soluo 1: utilizar a interface Callable

    Soluo 2: retornar os valores em um objeto compartilhado

    Problemas de sincronizao em dados compartilhados (veremos mais adiante)

    Adotemos a soluo 1...

  • Interface Callable

    Callable: generic possibilitando definir o tipo de retorno

    Mtodo call: ponto de entrada para a Thread (ao invs do mtodo run()), retornando o tipo definido no generic Callable

  • Exemplo: Callable(1)

    public class ThreadCallable implements

    Callable{

    private static Random generator= new Random();

    public int call(){

    return generator.nextInt(1000);

    }

    }

  • Exemplo: Callable(2)import java.util.concurrent.ExecutionException;

    import java.util.concurrent.ExecutorService;

    import java.util.concurrent.Executors;

    import java.util.concurrent.Future;

    import java.util.ArrayList;

    public class MainCallable {

    public static void main(String[] args) {

    ExecutorService executor= Executors.newCachedThreadPool();

    ArrayList resultados= new ArrayList();

    for (int i=0; i < 10; i++)

    resultados.add(executor.submit(new ThreadCallable()));

    executor.shutdown();

    for (int i=0; i< resultados.size(); i++){

    try {

    Future result;

    result = resultados.get(i);

    System.out.println(result.get());

    } catch (InterruptedException ex) {

    ex.printStackTrace();

    } catch (ExecutionException ex) {

    ex.printStackTrace();

    }

    }

    }

    }

  • Exerccio

    Faa uma aplicao Java multithread para buscar um dado elemento em um vetor (desordenado). Utilize um objeto Random para gerar numeros aleatrios Cada Thread ficar responsvel pela busca em uma

    parte do vetor

    Retorne a posio do elemento no vetor ou 1 caso o elemento no foi encontrado

  • ThreadFactory

    Um Executor utiliza padro de projeto Factory para criar as Threads

    O desenvolvedor pode criar sua prpria ThreadFactory para criar threads Definir atributos especficos

    Definir prioridades durante a criao de threads

    Definir manipuladores de exceo

  • ThreadFactory(1)import java.util.concurrent.*;

    public class MyThreadFactory implements ThreadFactory{

    private static int count;

    public MyThreadFactory(){

    count=0;

    }

    public Thread newThread(Runnable r) {

    Thread t= null;

    t = new Thread(r);

    count++;

    t.setName("MinhaThread[" + count + "]");

    return t;

    }

    }

  • ThreadFactory(2)Classe MyThread

    public class MyThread implements Runnable {

    public void run() {

    System.out.print(Thread.currentThread().getName());

    System.out.println(Thread.currentThread().getId());

    }

    }

    ----

    Classe principal

    import java.util.concurrent.*;

    public class MainTreadFactory {

    public static void main(String[] args) {

    ExecutorService executor=Executors.newFixedThreadPool(10, new MyThreadFactory());

    for (int i=0; i < 10; i++)

    executor.execute(new MyThread());

    executor.shutdown();

    }

    }

  • Exerccio

    No exerccio anterior, foi utilizado um gerenciador de Threads com nmero fixo. Substitua por um gerenciador dinmico (Executors.newCachedThreadPool(new MyFactoryThread()) Existe alguma diferena na sada gerada?

  • Tratando exceptionimport java.util.concurrent.*;

    public class ExceptionThread implements Runnable {

    public void run() {

    throw new RuntimeException();

    }

    public static void main(String [] args) {

    ExecutorService exec = Executors.newCachedThreadPool() ;

    exec.execute(new ExceptionThread());

    exec.shutdown();

    }

    }

  • Tratando internamenteimport java.util.concurrent.*;

    public class ExceptionThread implements Runnable {

    public void run() {

    try {

    throw new RuntimeException();

    catch (Exception ex){

    ex.printStackTrace();

    }

    }

    public static void main(String [] args) {

    ExecutorService exec = Executors.newCachedThreadPool() ;

    exec.execute(new ExceptionThread());

    exec.shutdown();

    }

    }

  • Tratando exception(2)/ / : concurrency/NaiveExceptionHandling.java

    import java.util.concurrent.*;

    public class NaiveExceptionHandling {

    public static void main(String[] args) {

    try {

    ExecutorService exec= Executors.newCachedThreadPool();

    exec.execute(new ExceptionThread()) ;

    exec.shutdown();

    } catch(RuntimeException ue) {

    // Esse cdigo no executar!!

    System.out.println("Exception has been handled!");

    }

    }

    }

  • Registrando um tratador de excees

    Como pegar excees que no so tratadas internamente nas Threads?

    Registrar um tratador de excees durante a criao de uma thread (ThreadFactory) Interface Thread.UncaughtExceptionHandler

    public void uncaughtException(Thread t,Throwable e)

  • Tratador de excees(1)public class MyThreadFactory implements ThreadFactory{

    public Thread newThread(Runnable arg0) {

    Thread t=new Thread(arg0);

    t.setUncaughtExceptionHandler(new TrataException());

    return t;

    }

    }

    class TrataException implements UncaughtExceptionHandler{

    public void uncaughtException(Thread arg0, Throwable arg1) {

    System.out.println("Tratador da exceo da Thread");

    }

    }

  • Tratador de excees(2)class MyThread implements Runnable{

    public void run(){

    throw new RuntimeException();

    }

    }

    public class MainUncaughtException {

    public static void main(String[] args) {

    ExecutorService executor= Executors.newCachedThreadPool(new

    MyThreadFactory());

    for (int i=0; i < 5 ; i++)

    executor.execute(new MyThread());

    }

    }

  • Sincronizao entre threads

    Acesso a variveis compartilhadas

  • Sincronizao

    Programa concorrente Executado por diversos processos

    Acesso concorrente a dados

    Paralelismo real x Paralelismo aparente Multiprocessadores: paralelismo real

    Paralelismo aparente: concorrncia

  • Programas concorrentes

    Processos seqenciais que executam concorrentemente (afetam ou so afetados por outros programas)

    Motivao Aumento de desempenho em mquinas

    multiprocessadas

    Interface com o usurio

    Sobreposio de operaes de E/S e processamento

  • Problema produtor-consumidor

    Seja um buffer compartilhado entre dois processos/threads. O processo produtor coloca dados em um buffer que so retirados pelo processo consumidor

    Possvel implementao Uma varivel count armazena o nmero de posies

    preenchidas no buffer Inicialmente armazena o valor 0 Quando o processo produtor coloca um dado no buffer,

    count incrementado Quando o processo consumidor retira o dado do buffer,

    count decrementado

  • Produtor

    while (true) {

    /* produce an item and put in nextProduced */

    while (count == BUFFER_SIZE)

    ; // do nothing

    buffer [in] = nextProduced;

    in = (in + 1) % BUFFER_SIZE;

    count++;

    }

  • Consumidor

    while (true) {

    while (count == 0)

    ; // do nothing

    nextConsumed = buffer[out];

    out = (out + 1) % BUFFER_SIZE;

    count--;

    /* consume the item in nextConsumed

    }

  • Condio de corrida

    count++ ou count register= count

    register= count+1

    count= register Considere a execuo intercalada com count = 5

    inicialmente:S0: produtor executa register1 = count {register1 = 5}S1: produtor executa register1 = register1 + 1 {register1 = 6} S2: consumidor executa register2 = count {register2 = 5} S3: consumidor executa register2 = register2 - 1 {register2 = 4} S4: produtor executa count = register1 {count = 6 } S5: consumidor executa count = register2 {count = 4}

  • Problema da seo crtica

    Condio de corrida: vrios processos/threadmanipulam conjuntos de dados onde o resultado depende da ordem de execuo

    Seo crtica: trecho de cdigo onde somente um processo pode executar por vez

  • Soluo

    Criar um protocolo que garanta a excluso mtua Execuo da seo crtica por somente um

    processo/thread

  • Propriedades da seo crtica

    Regra 1: Excluso mtua Regra 2: Progresso

    Nenhum processo fora da seo crtica pode bloquear um outro processo

    Regra 3: Espera limitada Nenhum processo pode esperar infinitamente para

    entrar na seo crtica

    Regra 4 Nenhuma considerao sobre o nmero de

    processadores ou velocidades relativas

  • Acesso concorrente a dados

  • Classe Contapublic class Conta {

    int saldoPoupanca;

    int saldoCC;

    public Conta(int _saldoPoupanca, int _saldoCC){

    saldoPoupanca= _saldoPoupanca;

    saldoCC= _saldoCC;

    }

    public void transferePoupanca(int v){

    saldoCC -= v;

    saldoPoupanca +=v;

    }

    public void transfereCC(int v){

    saldoPoupanca -=v;

    saldoCC +=v;

    }

    public int saldoTotal(){

    return (saldoPoupanca + saldoCC);

    }

    }

  • Produtorpublic class Produtor implements Runnable{

    private Conta c;

    private Random r= new Random();

    public Produtor(Conta _c){

    c= _c;

    }

    public void run(){

    while (true){

    c.transfereCC(r.nextInt(1000));

    c.transferePoupanca(r.nextInt(500));

    }

    }

    }

  • Consumidorpublic class Consumidor implements Runnable{

    private Conta c;

    private int saldoInicial;

    public Consumidor(Conta _c, int _saldoInicial){

    c= _c;

    saldoInicial=_saldoInicial;

    }

    public void run(){

    int saldo;

    while (true){

    saldo= c.saldoTotal();

    if (saldo != saldoInicial){

    System.out.println("Saldo errado = "+saldo);

    Thread.currentThread().yield();

    }

    }

    }

    }

  • Sincronizando acessos concorrentes

    Synchronized Evita a execuo concorrente das threads

    Como definir a sincronizao Mtodos

    public synchronized transfereCC(int v); public synchronized transferePoupanca(int v); public synchronized saldoTotal();

    Quando um mtodo definido como synchronized, ocorre um bloqueio, evitando a execuo No mtodo Entre mtodos synchronized da classe

  • Exerccio

    1) Altere o cdigo da transferncia de conta para que o mesmo funcione corretamente

    2) Verifique o funcionamento da aplicao SerialNumberGenerator

    a) Identifique o problema

    b) Faa as alteraes necessrias

  • Utilizando tipos de dados sincronizados

    AtomicInteger, AtomicLong boolean compareAndSet(expectedValue,

    updateValue);

    addAndGet (int delta)

    incrementAndGet()

    AtomicReference boolean compareAndSet(expectedValue,

    updateValue);

    getAndSet(V newValue)

  • Tipos de dados sincronizados

    Os tipos Queue (fila) LinkedQueue (lista) no pacote java.util no so sincronizados

    Tipos de dados thread-safe so definidos no pacote java.util.concurrent

    Interface BlockingQueue() Classe: ArrayBlockingQueue

    void put(E e);

    E take();

  • ArrayBlockingQueue

    class Main() {

    // Instanciando

    private ArrayBlockingQueue buffer= new

    ArrayBlockingQueue(5); // buffer de 5 posies

    }

    // inserindo elementos no buffer

    buffer.put(new Integer(5));

    //removendo elementos do buffer

    valor= buffer.take();

  • Exerccio

    Implemente duas Threads, uma produtora e uma consumidora O Produtor dever gerar 1000 nmeros e colocar

    no buffer compartilhado para ser consumido pela Thread Consumidor

    Utilize a classe BlockingQueue como buffer compartilhado

  • Material complementar

  • Semforos

    Proposto por Dijkstra(1965)

    Sincronizao que no necessita de espera ativa

    Semforo S varivel inteira

    Duas operaes S: acquire() e release()

    Operaes atmicas

  • Semforo

    Binrio: varia entre 0 e 1

    Contador: valor inteiro

  • Implementao de semforos

    Deve garantir que dois processos no executem acquire () e release () no mesmo semforo ao mesmo tempo

    A implementao do acquire e release torna-se o problema de seo crtica. Espera ativa

    Algumas aplicaes podem ficar muito tempo na seo crtica.

  • Implementao de semforo sem espera ativa

    Cada semforo tem sua fila de espera. Cada posio da fila de espera tem dois campos: valor (tipo inteiro)

    ponteiro para o prximo elemento da lista

  • Duas operaes:

    block coloca o processo que esta adquirindo o semforo na fila apropriada.

    wakeup remove o processo que esta na fila de espera e coloca na fila de prontos.

  • Implementao de semforo sem espera ativa

    Acquire()

    Release()

  • Semafros em Java Exemplo:import java.util.concurrent.Semaphore;

    public class ThreadInterface implements Runnable{

    Semaphore sem= new Semaphore(1);

    public void run() {

    sem.acquire();

    for (int i=0; i

  • Bloqueios e variveis de condio

    Menor overhead que semforos e synchronized

    Implementao mais eficiente no Java

    Variveis de condio so utilizadas caso seja necessrio bloquear a execuo no meio da seo crtica

  • Exemplo: Lockimport java.util.concurrent.locks.*;

    public class ThreadInterface implements Runnable{

    Lock mutex= new Lock();

    public void run() {

    mutex.lock();

    for (int i=0; i

  • Exemplo: Variveis de condioclass ProducerConsumer {

    Lock mutex= new Lock();

    Condition cond= mutex.newCondition();

    static class Produtor extends Runnable{

    public void run() {

    while (true) {

    mutex.lock();

    while (count == BUFFER_SIZE)

    cond.await();

    buffer [in] = nextProduced;

    in = (in + 1) % BUFFER_SIZE;

    count++;

    cond.signal();

    }

    }

    }

    static class Consumidor extends Runnable{

    public void run() {

    while (true) {

    mutex.lock();

    while (count == 0)

    cond.await();

    nextConsumed= buffer[out];

    out = (out + 1) % BUFFER_SIZE;

    count--;

    cond.signal();

    }

    }

    }

    ..

    ..// mtodo Main

    }

  • Deadlock e starvation

    Deadlock dois ou mais processsos esperam infinitamente por eventos que somente podem ser gerados por processos no estado de espera

    Seja S e Q dois semforos inicializados em 1

    P0 P1

    S.acquire(); Q.acquire();

    Q.acquire(); S.acquire();

    . .

    . .

    . .

    S.release(); Q.release();

    Q.release(); S.release();

    Starvation bloqueio indefinido.