+ XV Jornada de Cursos CITi Programação Concorrente Aula 7 Benito Fernandes Fernando Castor João Paulo Oliveira Weslley Torres
+ Como se executa uma thread?
+ Roteiro Executors Thread Pools Executors Interfaces
+ Executors Separar o gerenciamento e a criação de threads do resto da aplicação Executors encapsulam essas funções Interfaces Definem os três tipos de objetos executors Thread Pools o tipo mais comum de implementação de executor
+ Interfaces java.util.concurrent Executor Cria e gerencia um grupo de threads( thread pool) ExecutorService Subinterface de Executor Adiciona gerenciamento de ciclo de vida, para tarefas individuais ou para o executor em si ScheduledExecutorService Subinterface de ExecutorService Suporta a execução de tarefas futuras e/ou programadas
+ Executor Interface Provê um só método Execute() Substitui o idioma de criação de threads Runnable object Executor object Executa um comando, objeto runnable, em algum tempo futuro Pode executar nas mesma thread, numa nova thread ou numa pool;
+ Implementação de um Executor Exemplo
+
+ Exercício Implemente uma tarefa runnable que imprime o nome dela Implementar dois executor Executor A : Executa uma tarefa assincronamente Executor B : Executa uma tarefa sincronamente Pegar o objeto SerialExecutor Execute o as tarefas usando o SerialExecutor Dica: Execute várias tarefas do mesmo tipo para visualizar melhor os resultados
+ Thread Pools Coleção de threads disponíveis para realizar tarefas A maioria das implementações de executores em Java usa thread pools Consiste de worker threads As threads existem separadamente dos objetos Runnable e Callable que ela executa Executa múltiplas tarefas
+ Thread Pools, porque usar? Worker threads minimiza o overhead da criação de threads Threads usam uma quantidade significante de memória Melhor desempenho quando se executam um grande número de tarefas devido a um overhead reduzido de chamadas por tarefa Em sistema larga escala alocar e desalocar muitas threads gera um overhead significativo no gerenciamento da memória Uma forma de limitar recursos consumidos incluindo threads
+ Tolerância a falhas Caso a quantidade de requisições seja muito alta a aplicação não quebra As threads irão servir a aplicação na velocidade que ela mesma suportar Por exemplo Um web server onde cada request é manipulado por uma thread separadamente Criar nova thread para cada HTTP request ou limitar a criação de threads, processando os requests quando possível
+ Tamanho do pool É comum utilizar uma quantidade fixa de threads na pool Usando e reutilizando as worker threads quando disponível Caso uma thread é terminada ainda em uso ela é reposta por uma nova thread Tarefas submetidas a pool são enviadas para uma fila interna Essa fila armazena as tarefas quando existem mais tarefas ativas do que threads
+ Implementações de Pool ThreadPoolExecutor ScheduledThreadPoolExecutor Implementação permitem que se estabeleça: O numero de threads O tipo de estrutura que irá armazenar nas tarefas Como criar e finalizar as threads Porém é mais comum utilizar a factory Executors
+ ExecutorService Estende a interface Executor Complementa o método execute com submit Mais versátil Aceita objetos Runnable Também aceita objetos Callable Permite que a tarefa retorne um valor Retorna um objeto do tipo Future Captura o retorno do objeto Callable Gerencia os status tanto das tarefas Callable e Runnable Prove métodos que permitem submeter coleções de objetos Callable
+ Finalizando um ExecuteService ExecutorService pode ser terminado, que irá rejeitar novas tarefas shutdown Permite executar as tarefas anteriormente submetidas antes de ser finalizado shutdownnow Não permite que tarefas em espera inicializem Finaliza as tarefas que estão sendo executadas
+ Executors Factory Factory para as classes : Executor ExecutorService ScheduleExecutorService ThreadFactory Callable
+ Executors Factory Executor Service newfixedthreadpool(int nthreads) Cria um thread pool que reusa um número fixo de threads Operando numa fila ilimitada de tarefas E se uma thread falhar e terminar uma nova outra é colocada no lugar para executar as próximas tarefas newcachedthreadpool() Cria um pool que cria novas threads quando for necessário Ou seja, cria novas threads mas as reusa quando elas estão disponíveis Melhora desempenho de programas que executam tarefas curtas assincronamente Timout das threads em cache: 60 seg
+ Executors Factory newsinglethreadexecutor() Cria um Executor que usa uma única thread worker Operando numa fila ilimitada de tarefas Cria uma nova thread quando necessário(em caso de falha) Tarefas são garantidamente executadas em seqüência Não pode ser reconfigurado para usar mais threads
+ Criando um ExecutorService Iremos usar a factory Executors
+ Exemplo de Cached Thread Pool Usando Executors.newCachedThreadPool() Fonte: Argonavis, Helder Rocha
+ Exemplo de Fixed Thread Pool Usando Executors.newFixedThreadPool Fonte: Argonavis, Helder Rocha
+ Exemplo: SingleThreadExecutor Usando Executors.newFixedThreadPool Seq-um Seq-dois Seq-3 Seq-4 Main tempo
+ Exemplo: Servidor Fonte: Argonavis, Helder Rocha
+ Exercício Utilizando o código do Produtor/Consumidor Execute as tarefas através ExecutorService Finalize o executor assim que as tarefas terminarem Utilizando newsinglethreadexecutor Execute três tarefas em seqüência e uma em background Finalize o executor assim que as tarefas terminarem
+ Callable<V> Interface Função semelhante à de Runnable, mas com conteúdo que pode retornar valor ou exceção Pode ser usado no lugar de Runnable Utilizando o submit da classe do ExecutorService V Tipo de retorno do método call call Computa o resultado, ou lança uma exceção caso não consiga
+ Future<V> Interface Representa o resultado de uma operação assíncrona Permite saber se a tarefa foi concluída, esperar sua conclusão, recuperar o resultado e tentar cancelar a computação O resultado só pode ser capturado usando o método get Apenas quando o resultado estiver disponível Caso não, bloqueia até quando estiver pronto Normalmente usa-se Future como resultado de métodos submit() de ExecutorService que rodam Callable isdone: se a computação foi finalizada cancel: cancela a operação
+ Usando Future, Callable
+ FutureTask Implementação da interface Future e Runnable Pode ser executada por um Executor Podemos substituir a chamada do submit
+ Agendamento Encapsulam o uso de Timers e TimerTask Interface Delayed Retorna o atraso associado ao objeto que implementa esta interface ScheduleFuture Objeto Future
+ Agendamento - ScheduledExecutorService Estende ExecutorService Complementa com métodos para programar uma tarefa com um atraso Schedule Executa objetos Runnable e Callable Tempo do delay TimeUnit
+ Agendamento - ScheduledExecutorService Executam tarefas repetidamente no intervalo definido scheduleatfixedrate Command, initialdelay, period, TimeUnit schedulewithfixeddelay Command, initialdelay, delay, TimeUnit
+ Exemplo - Schedule
+ Exercício Execute através de um pool de threads a classe PrintTask E ao fim das execuções finalize o ExecuteService Altere a quatidade de threads na pool e verifique o resultado Utiliza a classe PrintTask para imprimir peridicamente Altere a classe PrintTask de modo que o ExecutorService use o método submit Retornando o nome da thread Dica: Utilize os objetos Future e Callable
+ Referências http://download.oracle.com/javase/tutorial/essential/concurrency/executors.ht ml