Processamento. Paralelo. e a nova API Fork/Join

Tamanho: px
Começar a partir da página:

Download "Processamento. Paralelo. e a nova API Fork/Join"

Transcrição

1 capa_ Processamento Paralelo e a nova API Fork/Join Desenvolva código que faz uso de diferentes implementações da interface ExecutorService e entenda como funciona a nova API Fork/Join. A linguagem Java oferece uma rica API que pode facilitar o desenvolvimento de software que faz uso de processamento paralelo. Em sua versão mais atual é introduzida uma nova implementação para a interface ExecutorService, chamada ForkJoinPool. Neste artigo estudaremos os recursos da linguagem desde suas primeiras versões até a sua versão mais atual. Resolveremos dois problemas (ordenação e média móvel) de formas diferentes e faremos comparações entre as soluções propostas, ilustrando o uso de diferentes recursos oferecidos pela linguagem, com maior ênfase na nova API Fork/Join. Neste artigo faremos uma breve viagem desde as primeiras versões da linguagem Java até a sua versão mais atual, descrevendo os principais recursos oferecidos em cada versão da linguagem. Em seguida, aplicamos os recursos descritos para solucionar dois problemas interessantes. Procuramos tornar o entendimento do artigo mais sólido oferecendo diferentes soluções para cada problema. Falar de processamento paralelo sem falar de possíveis ganhos de desempenho é improvável. Assim, durante o artigo, procuramos comentar sobre resultados obtidos comparando o tempo de execução de cada solução. Runnable, Thread e seus problemas Nas primeiras versões do Java, criava-se programas multithreaded utilizando-se a classe Thread e a interface Runnable. Escrever programas utilizando esta API básica é simples. Uma classe que implementa a interface Runnable representa uma unidade executável. A interface Runnable define um método chamado run, que é onde devemos colocar o código que deve ser executado por uma thread diferente da thread principal do programa. Com um objeto Runnable em mãos, criamos um objeto da classe Thread e indicamos que ele deve executar o método run do objeto Runnable que criamos. Assim temos / 6

2 Rodrigo Bossini Atualmente cursa mestrado em Ciência da Computação pelo Instituto de Matemática e Estatística da Universidade de São Paulo. É professor do Centro Universitário FIEO, ministrando disciplinas como Teoria da Computação e Estruturas de Dados. Atua como tutor virtual do curso de Sistemas de Informação da Universidade Federal de São Carlos. Possui as certificações SCJP e SCWCD. Graduado em Ciência da Computação pelo Centro Universitário FIEO. algo parecido com os trechos de código mostrados nas Listagens 1 e 2. Listagem 1. Uma classe que representa uma tarefa a ser executada implementa a classe Runnable. class MinhaUnidadeExecutavel implements public void run() { System.out.println( Código a ser executado pela nova thread. ); Listagem 2. Criando uma nova thread e iniciando a mesma. O construtor recebe uma instância de nossa classe que implementa Runnable. A nova thread executa o método run, implementado pela nossa classe. Thread t = new Thread(new MinhaUnidadeExecutavel()); t.start(); Na Listagem 2, a thread referenciada por t executará o método run do objeto que passamos ao construir o objeto Thread. A partir da linha t.start() existem pelo menos duas threads candidatas a execução em nosso programa: a thread principal (que executa o método main) e a thread referenciada por t. A própria classe Thread implementa a interface Runnable, assim também temos a opção de criar uma classe que herda da classe Thread diretamente e sobrescreve seu método run. Essa forma em geral não é recomendada já que estaríamos desperdiçando a possibilidade de herança e estaríamos criando objetos que passam no teste é um Thread, mas que em geral não representam de fato uma Thread. Esta API básica é simples de usar, mas pode dar dor de cabeça. Suponha que temos uma lista de clientes para os quais desejamos executar alguma atividade e que gostaríamos de executar a atividade de cada cliente em uma thread separada. Utilizando essa API simples, teríamos algo como o trecho de código mostrado na Listagem 3. Listagem 3. Temos uma lista de clientes para os quais desejamos executar uma tarefa específica. Executar as tarefas em threads separadas é bastante simples. Collection <Cliente> clientes = getcolecao(); for (Cliente cliente: clientes){ //Tarefa implementa Runnable e seu método run contém o código a ser executado para cada cliente new Thread(new Tarefa(cliente)).start(); O exemplo de código da Listagem 3 pode dar dor de cabeça por algumas razões. A coleção de clientes pode ser arbitrariamente grande. E se tivermos um milhão de clientes? Estaríamos criando um milhão de threads, uma para cada cliente. Instanciar threads é um processo caro. Cada uma dessas threads poderia estar tentando acessar uma base de dados. Já pensou em escrever um programa que abre um milhão de conexões com o SGBD simultaneamente? O que gostaríamos de verdade é criar um número limitado de threads e reutilizá-las. Infelizmente, threads somente podem ser iniciadas uma vez. Não poderíamos, por exemplo, instanciar uma única thread e iniciá-la duas vezes, uma para cada cliente. O pacote java.util.concurrent do Java 5 O Java 5 introduziu o pacote java.util.concurrent que, entre outras coisas, oferece algo conhecido como pool de threads. Um pool de threads encapsula um conjunto de threads trabalhadoras e uma fila de tarefas a serem executadas. Submetemos tarefas a serem executadas a um pool de threads. As mesmas são enfileiradas e executadas por uma das threads trabalhadoras do pool que estiver disponível. Seu funcionamento se assemelha muito ao paradigma conhecido como produtor-consumidor. Dessa forma, um pool de threads pode criar um número limitado de threads e reutilizá-las para inúmeras tarefas. As principais interfaces do pacote java.util.concurrent para se trabalhar com pools de threads são as seguintes: Executor: define apenas um método chamado execute que recebe um objeto Runnable e executa seu método run, possivelmente em uma nova thread. A documentação oficial permite que a mesma thread que chama o método execute execute o método run do objeto Runnable recebido. ExecutorService: estende a interface Executor e define métodos que permitem, entre outras coisas, rastrear o progresso de atividades submetidas e cancelar a execução das mesmas. Callable: um pool de threads pode executar objetos Runnable, mas objetos Runnable não podem retornar resultados ou lançar exceções checadas. A interface Callable é similar à interface Runnable, definindo um método call que é parecido com o método run de Runnable, mas que pode retornar um valor e lançar exceções. O pacote java.util.concurrent oferece algumas implementações para a interface ExecutorService. 7 \

3 As mesmas podem ser obtidas utilizando-se métodos estáticos da classe Executors, como a seguir: Executors.newFixedThreadPool: retorna uma implementação de ExecutorService que representa um pool de threads com número de threads trabalhadoras fixo. Quando há mais tarefas a serem executadas do que threads trabalhadoras disponíveis, as tarefas são enfileiradas. Threads podem ficar ociosas caso não haja tarefas a executar. Executors.newCachedThreadPool: retorna uma implementação de ExecutorService que representa um pool de threads que cria e destrói threads trabalhadoras sob demanda. Quando tarefas são submetidas elas são executadas por threads disponíveis. Caso não haja thread disponível, uma nova é criada para cada nova tarefa submetida. Threads ociosas são destruídas após certo tempo de ociosidade. Executors.newScheduledThreadPool: retorna uma implementação de ExecutorService (na verdade de ScheduleExecutorService, que é uma interface que estende ExecutorService e define métodos relacionados ao agendamento de tarefas) que permite agendar tarefas para serem executadas periodicamente por uma das threads trabalhadoras ou para serem executadas uma vez após um intervalo determinado. Nova implementação de ExecutorService no Java 7 e as classes RecursiveAction e RecursiveTask Uma nova implementação para a interface ExecutorService é introduzida na versão 7 do Java: ForkJoinPool. O que há de novo nesta implementação em relação às implementações oferecidas no Java 5? A classe ForkJoinPool implementa um algoritmo de roubo de trabalho (work-stealing), o que significa que threads ociosas podem eventualmente roubar trabalho de outras threads que estiverem ocupadas. Quando trabalhamos com um ForkJoinPool, idealmente temos tarefas que exibem uma estrutura recursiva: elas podem ser definidas em função de versões menores delas mesmas. Suponha que temos um problema que pode ser definido em função de versões menores dele mesmo e que versões pequenas o suficiente desse problema têm solução já conhecida, que não precisa de cálculo algum. Por exemplo, o problema do cálculo do fatorial de um número pode ser definido em função de versões menores dele mesmo. Basta observar que n! é igual a n * (n-1)!. Ou seja, se sabemos calcular (n-1)! (uma versão menor do problema original) então sabemos calcular n! também. Além disso, a solução para n! quando n=0 ou n=1 é conhecida. Essa observação é importante, pois nossas soluções recursivas devem sempre convergir para um caso simples de se resolver, o que é similar à condição de parada de um loop. Na verdade, todo problema que pode ser resolvido de modo iterativo pode ser resolvido de modo recursivo também (embora nem sempre uma solução recursiva seja tão eficiente quanto uma solução iterativa). Até mesmo o problema da impressão de uma sequência de n números inteiros pode ser definido em função de versões menores dele mesmo. Para imprimir uma lista de inteiros recursivamente, observamos que se a lista contém mais de um elemento, basta fazermos a impressão do primeiro elemento da lista e então fazer a impressão da lista que começa do número seguinte em diante. Caso a lista tenha um número só, basta fazer sua impressão e terminar, sem a necessidade de uma chamada recursiva. Utilizar a API Fork/Join para solucionar problemas recursivamente e fazendo uso de processamento paralelo é bastante simples. Um ForkJoinPool pode trabalhar com objetos Runnable e Callable. Além disso, o Java 7 introduz a classe abstrata ForkJoinTask cujas extensões podem ser executadas por um ForkJoinPool. São oferecidas duas extensões para a classe ForkJoinTask: RecursiveAction e RecursiveTask. Se desejarmos executar uma atividade em um ForkJoinPool usando uma dessas classes, devemos criar uma subclasse que herde da classe desejada e implementar o método abstrato compute, cujo funcionamento é similar aos métodos run e call das interfaces Runnable e Callable. Ou seja, ao submetermos um objeto ForkJoinTask a um ForkJoinPool, o método compute será executado por uma das threads do pool (ao menos teoricamente, já que oficialmente a atividade pode ser executada até mesmo pela thread que submeteu a atividade ao pool). O método compute de uma classe que herda de RecursiveAction não tem retorno algum (assim como o método run de Runnable) e o método compute de uma classe que herda de RecursiveTask pode ter um retorno (assim como o método call de Callable). As classes RecursiveAction e RecursiveTask fornecem métodos que tornam bem simples soluções para problemas com estrutura recursiva. Em especial, a classe abstrata ForkJoinTask (que é herdada por ambas RecursiveAction e RecursiveTask) define métodos que permitem que uma tarefa tenha acesso ao pool de threads a que a thread que a está executando pertence. Assim, o código da nossa tarefa pode submeter subtarefas diretamente ao pool de threads sendo utilizado, que eventualmente serão executadas por diferentes threads trabalhadoras. Solução de problemas Vamos agora aplicar os recursos disponíveis na linguagem Java para solucionar dois problemas diferentes. Primeiro iremos solucionar o conhecido problema de ordenação de uma coleção de números. Implementaremos o algoritmo de ordenação Quick- Sort. Faremos isso de duas formas diferentes: na primeira, usamos somente os recursos disponíveis antes / 8

4 da versão 7 do Java. Depois disso, implementaremos uma solução para o mesmo problema utilizando as classes ForkJoinPool e RecursiveAction do Java 7. No segundo problema, faremos o cálculo da média móvel de uma coleção de valores, obtendo o valor máximo das médias. Faremos duas implementações para esse problema. Uma delas será puramente sequencial não usaremos processamento paralelo. Em seguida, implementaremos uma nova solução para o mesmo problema utilizando a classe RecursiveTask (que permite o retorno de um valor) do Java 7. Ao final, faremos uma comparação entre os tempos de execução de cada solução. Problema 1: Ordenação Primeiro, mostramos uma implementação utilizando somente recursos disponíveis antes da versão 7 do Java. Depois mostramos uma solução utilizando as classes ForkJoinPool e RecursiveAction, ambas disponíveis a partir do Java 7. O algoritmo QuickSort A implementação que faremos do algoritmo de ordenação QuickSort baseia-se inteiramente no pseudocódigo oferecido em [1]. O algoritmo de ordenação QuickSort baseia-se na seguinte ideia: suponha que desejamos ordenar uma lista de números armazenada em um vetor. Um dos números do vetor a ser ordenado é escolhido arbitrariamente (esse número é, geralmente, chamado de pivô adotamos esse nome aqui também). Os números no vetor são organizados de modo que o número escolhido como pivô fique em um índice q tal que todos os números nos índices entre 0 e q -1 sejam menores ou iguais ao pivô e todos os números a partir do índice q+1 sejam maiores do que o pivô. Por exemplo, considere o vetor mostrado na figura 1. Figura 1. Uma coleção de números armazenada em um vetor Caso o número 8 seja escolhido como pivô, por exemplo, após a organização do vetor espera-se que ele esteja como a figura 2. Figura 2. O mesmo vetor após a escolha do pivô. Neste exemplo escolhemos o número 8 como pivô e organizamos o vetor de modo que todos os números menores ou iguais ao pivô fiquem à sua esquerda e o restante fique à sua direita Todos os números menores ou iguais a 8 aparecem à esquerda e o restante aparece à direita. Repare que se fosse escolhido o 13 (1) como pivô, teríamos números somente à esquerda (direita) do pivô. A escolha do pivô tem impacto na complexidade computacional do algoritmo QuickSort, mas este é um tema que não será discutido aqui. Para mais informações, veja [1]. Com o vetor organizado como mostrado na figura 2, observa-se o seguinte: para concluir a ordenação do vetor, basta aplicar o mesmo procedimento ao subvetor [1..q-1] e ao subvetor [q+1..n-1]. Ou seja, aplicamos o algoritmo QuickSort para ordenar os subvetores à esquerda e à direita do pivô. Se esses vetores forem pequenos o suficiente (vazios ou contendo um único elemento) eles já podem ser considerados ordenados e não há nada o que fazer. Caso contrário, executamos o mesmo procedimento (escolhendo um novo pivô em cada um dos subvetores e organizando-os adequadamente). No final, o vetor completo estará ordenado. Vamos implementar uma classe que contém os métodos necessários para a implementação do QuickSort. Esta mesma classe será utilizada em ambos os exemplos que faremos. Inicialmente, criamos uma classe (que chamaremos de QuickSort) que contém três variáveis de instâncias: o vetor a ser ordenado e dois inteiros que indicam os índices inicial e final entre os quais desejamos que seja feita a ordenação no vetor. Esta classe aparece na Listagem 4. É óbvio que desejamos que o vetor completo seja ordenado. A utilidade desses dois índices ficará mais clara quando fizermos chamadas recursivas para ordenar os subvetores à esquerda e à direita do pivô. Listagem 4. A classe QuickSort e suas variáveis de instância. class QuickSort{ double [] vetor; int inicio; int fim; Escrevemos agora um método que chamaremos de partição. Esse método é o responsável pela escolha do pivô e pela organização do vetor, garantindo que valores menores ou iguais ao pivô aparecem à sua esquerda e todos os demais aparecem à sua direita. O método retorna o índice do vetor em que o pivô ficou armazenado após essa organização. Sua implementação aparece na Listagem 5. Listagem 5. A implementação do método partição. Fazemos a escolha do pivô e organizamos o vetor adequadamente, retornando o índice em que o pivô ficou armazenado. int particao(){ double pivo = vetor[fim]; int i = inicio - 1; for (int j = inicio; j < fim; j++){ if (vetor[j] <= pivo){ i++; 9 \

5 troca(i,j); troca(i+1, fim); return i + 1; O método particao faz uso de outro método chamado troca. O método troca recebe dois inteiros que representam índices no vetor e faz a troca dos valores contidos nesses índices. Sua implementação é dada na Listagem 6. Listagem 6. O método troca recebe dois parâmetros inteiros i e j e faz a troca dos valores contidos nas posições i e j do vetor. void troca(int i, int j){ double temp = vetor[i]; vetor[i] = vetor[j]; vetor[j] = temp; Adicionamos também um construtor que nos permite passar valores para as variáveis de instância, conforme mostra a Listagem 7. Listagem 7. Um construtor para a classe QuickSort que permite a passagem de valores para suas variáveis de instância. QuickSort(double [] vetor, int inicio, int fim){ this.vetor = vetor; this.inicio = inicio; this.fim = fim; Implementação utilizando recursos anteriores ao Java 7 Vamos escrever uma classe que emprega os recursos anteriores ao Java 7 para fazer a execução do algoritmo QuickSort em paralelo. Inicialmente, é feita a partição do vetor e em seguida submetemos ao pool de threads duas novas atividades: uma para ordenar o subvetor à esquerda do pivô e outra para ordenar o subvetor à direita do pivô. Essas duas atividades possivelmente serão executadas por threads diferentes do pool de threads. Chamaremos nossa classe de QSJava5. Ela tem uma variável de instância do tipo QuickSort e uma referência a um Executor- Service. Veremos que essa variável será importante quando tentarmos submeter subproblemas (a ordenação dos vetores à esquerda e à direita do pool) ao pool. Essa variável não será necessária na solução que desenvolvermos na seção utilizando recursos do Java 7, pois uma thread trabalhadora de um ForkJoinPool tem acesso ao pool a que pertence, o que não ocorre com uma thread pertencente a uma implementação simples de ExecutorService. Nossa classe implementa a interface Callable de modo que suas instâncias possam ser submetidas a um ExecutorService para execução. Poderíamos ter usado a interface Runnable também. Optamos por Callable, pois o método call de Callable permite o lançamento de exceção (o que pode acontecer ao chamar o método get de Future). Utilizando Runnable teríamos que envolver a chamada ao método get de Future em um bloco try/catch. O método call de Callable retorna um valor. Neste caso, não desejamos retorno algum, já que o resultado final (o vetor ordenado) estará armazenado no próprio vetor inicial, para o qual já temos uma referência. A Listagem 8 mostra a classe QSJava5 e suas variáveis de instância. Listagem 8. A classe QSJava5 e suas variáveis de instância. class QSJava5 implements Callable <Void>{ ExecutorService pool; QuickSort quicksort; Escrevemos um construtor que nos permita passar valores para as variáveis de instância da classe, conforme mostra a Listagem 9. Listagem 9. Um construtor para a classe QSJava5 que nos permite passar valores para suas variáveis de instância. Um objeto do tipo QuickSort é construído com valores adequados. QSJava5(double [] vetor, int inicio, int fim, ExecutorService pool ) { this.quicksort = new QuickSort(vetor, inicio, fim); this.pool = pool; E agora a parte principal. Sobrescrevemos o método call de Callable. O método verifica se o vetor a ser ordenado contém pelo menos dois elementos. Nesse caso, o início é estritamente menor do que fim. O pivô é escolhido e o vetor é organizado pelo método partição, cujo retorno é armazenado na variável meio. Neste momento, desejamos submeter ao pool duas novas atividades. Uma delas deve ordenar o subvetor [inicio..meio-1] e a outra deve ordenar o subvetor [meio+1..fim]. Essa é a razão pela qual precisamos de uma variável ExecutorService na nossa classe. Precisamos de acesso ao pool para fazer a chamada ao método submit, indicando as novas atividades a serem executadas. Essas atividades serão, possivelmente, executadas por diferentes threads do pool de threads. Além disso, antes que possamos considerar o vetor completamente ordenado, precisamos ter certeza de que os dois subvetores mencionados / 10

6 foram ordenados. Essa é a razão pela qual precisamos chamar o método get nos dois objetos Future que obtivemos ao submeter às subtarefas ao pool. O método get é bloqueante e só retorna quando a atividade associada àquele Future tiver sido executada completamente. A implementação do método call é mostrada na Listagem 10. Listagem 10. Implementação do método call. Caso o vetor tenha pelo menos dois elementos, aplicamos o método partição para selecionar o pivô e organizá- -lo adequadamente. Após isso, submetemos ao pool de threads duas novas tarefas: ordenar o subvetor [inicio.. meio-1] e ordenar o subvetor [meio+1]. As chamadas ao método get da interface Future são bloqueantes. Garantimos que o vetor somente será considerado completamente ordenado depois que os subvetores à direita e à esquerda do pivô estejam ordenados, ou seja, quando as chamadas ao método get public Void call() throws Exception { if (quicksort.inicio < quicksort.fim){ int meio = quicksort.particao(); Future <?> f1 = pool.submit( new QSJava5(quickSort.vetor,quickSort.inicio, meio - 1,pool)); Future <?> f2 = pool.submit( new QSJava5(quickSort.vetor, meio + 1, quicksort.fim,pool)); f1.get(); f2.get(); return null; Agora escrevemos um código cliente para testar nossa aplicação. Obtemos uma instância de ExecutorService usando o método estático Executors. newcachedthreadpool. Essa escolha é fundamental para o correto funcionamento de nosso algoritmo. Se escolhêssemos um pool com número fixo de threads, correríamos o risco de a execução nunca terminar. Por exemplo, suponha que utilizamos um pool de threads com uma única thread trabalhadora. A princípio, submetemos a tarefa completa ao pool, que obviamente será executada pela única thread trabalhadora existente. O que acontece quando submetermos as duas subtarefas ao pool? Essa única thread ficará esperando pelo resultado e nunca obterá, pois ela é a única que poderia fazer o processamento. Nossa escolha garante o funcionamento do algoritmo, mas tem um problema: um número arbitrário de threads pode ser adicionado ao pool até que o problema seja resolvido. Para vetores muito grandes, é possível que nosso programa termine com um indesejado OutOf- MemoryError. Testamos nossa implementação com o código mostrado na Listagem 11. Listagem 11. Código que testa nossa implementação paralela de QuickSort utilizando a API anterior ao Java 7. Geramos um vetor com números aleatórios e submetemos o problema inicial (ordenar o vetor a partir do índice 0 até o índice vetor.length 1 inclusive) ao pool de threads. A chamada ao método get é importante para garantir que a thread principal somente prossiga em sua execução após o problema ter sido resolvido por completo. Ao final, imprimimos o tempo gasto em milissegundos e fechamos o pool de threads. public static void main(string[] args)throws Exception{ Random random = new Random(); int n = 2000; double [] vetor = new double [n]; for (int i = 0; i < n; i++){ vetor[i] = random.nextdouble(); ExecutorService pool = Executors.newCachedThreadPool(); long inicio = System.currentTimeMillis(); Future <?> result = pool.submit(new QSJava5(vetor, 0, vetor.length - 1,pool)); result.get(); long fim = System.currentTimeMillis(); System.out.println((fim - inicio)); pool.shutdownnow(); Implementação utilizando recursos do Java 7 (RecursiveAction): Inicialmente, criaremos uma classe que herda de RecursiveAction e a chamaremos de QSJava7. Essa classe também precisa de uma variável de instância do tipo QuickSort, que oferece as implementações dos métodos partição e troca. Na seção anterior, implementamos o método call de Callable, que é o método executado pelas threads trabalhadoras do pool. Aqui, nossa classe herda de RecursiveAction e deve implementar o método compute, que é similar ao método call de Callable, mas não tem retorno algum. Sua implementação aparece na Listagem 12. Listagem 12. Implementação da classe QSJava7. Ela herda de RecursiveAction. Um construtor permite a passagem de valores para sua variável de instância. class QSJava7 extends RecursiveAction{ QuickSort quicksort; QSJava7(double [] vetor, int inicio, int fim){ quicksort = new QuickSort(vetor,inicio,fim); A classe QSJava7 representa uma atividade que pode ser executada em um ForkJoinPool. Na Listagem 13, fazemos a implementação do método abstrato 11 \

7 compute herdado de RecursiveAction. Listagem 13. Implementação do método compute herdado de RecursiveAction. Este método será executado por uma thread trabalhadora de um protected void compute() { if (quicksort.inicio < quicksort.fim){ int meio = quicksort.particao(); invokeall(new QSJava7( quicksort.vetor,quicksort.inicio, meio 1), new QSJava7(quickSort.vetor, meio + 1, quicksort.fim)); Graças ao método invokeall (herdado de RecursiveAction), não precisamos de uma referência ao pool de threads em que nossas atividades são executadas. Presume-se que a thread que executa o método invokeall seja uma thread trabalhadora pertencente a um pool de threads e ela deve ter uma referência ao pool a que pertence (a classe ForkJoinWorkerThread, que herda de Thread e representa threads trabalhadoras de um ForkJoinPool tem um método chamado getpool), de modo que possa submeter novas tarefas. Chamar o método invokeall a partir de uma thread que não pertença a um ForkJoinPool pode gerar uma RuntimeException. Em nossos testes, chamamos invokeall a partir da thread principal do programa, o que gerou uma ClassCastException. Internamente, o método tenta fazer um casting da thread que executa o método para o tipo ForkJoinWorkerThread. Na Listagem 14 mostramos um código cliente para testar nossa implementação. Listagem 14. Código cliente para testar nossa implementação que utiliza a API Fork/Join. Um ForkJoinPool é instanciado e submetemos uma instância de QsJava7 a ele. Obtemos um tempo de execução estimado e imprimimos o resultado na tela. public static void main(string[] args)throws Exception{ Random random = new Random(); int n = 2000; double [] vetor = new double [n]; for (int i = 0; i < n; i++){ vetor[i] = random.nextdouble(); ForkJoinPool poolforkjoin = new ForkJoinPool(); long inicio = System.currentTimeMillis(); poolforkjoin.invoke(new QSJava7(vetor, 0, vetor.length - 1)); long fim = System.currentTimeMillis(); System.out.println((fim - inicio)); Novamente geramos um vetor de números aleatórios para ser ordenado. Instanciamos um ForkJoin- Pool (repare que o tipo da variável de referência precisa ser ForkJoinPool também, para que possamos chamar o método invoke que recebe uma ForkJoin- Task) utilizando seu construtor padrão. O construtor cria um pool com o número de threads igual ao número de processadores disponíveis, obtido com Runtime.availableProcessors(). Uma versão sobrecarregada recebe um inteiro que indica o número de threads desejado. Esse número pode ser no máximo Passar um valor maior do que esse pode gerar uma RuntimeException (mais especificamente uma IllegalArgumentException). A chamada ao método invoke é bloqueante. A thread que o executa somente prossegue em sua execução após o término da atividade submetida ao pool. A documentação oficial sugere que se utilize esta API para problemas em que não existe necessidade de sincronização e memória compartilhada. Na nossa solução, apesar de todas as threads estarem atuando sobre o mesmo vetor, não existe memória compartilhada ou necessidade de sincronização. Primeiro aplicamos o particionamento (que atua sobre o vetor inteiro) e depois que ele foi particionado é que outras threads começam a atuar sobre intervalos diferentes do mesmo vetor. Para este problema, optamos pelo uso de RecursiveAction pela seguinte razão: apesar de necessitarmos de um resultado final (o vetor ordenado) não precisamos que ele seja retornado. As threads operam sobre o vetor original e o resultado final fica armazenado no próprio vetor, para o qual já temos uma referência. Problema 1 Conclusões A nova API Fork/Join torna simples elaborar soluções para problemas com estrutura recursiva. As medidas de tempos de execução realizadas não devem ser consideradas conclusivas. Em nossos testes, em geral, o código que usa a API Fork/Join sempre leva vantagem. Apesar disso, devemos atentar para o fato de que a implementação utilizando recursos do Java 5 faz uso de um pool de threads que criar threads arbitrariamente, o que é um processo custoso e certamente tem um impacto importante no tempo de execução do programa. Após a execução do programa que utiliza a API Fork/Join, pode ser interessante executar o método getstealcount de ForkJoinPool, que retorna uma estimativa do número de vezes em que houve roubo de trabalho entre as threads trabalhadoras do pool. Problema 2 Média móvel Nesta seção, introduzimos um novo problema: o cálculo da média móvel. Mostramos como implementar uma versão que não usa paralelismo e em seguida oferecemos uma possível implementação utilizando a API Fork/Join do Java 7. Fazemos também comparações quanto ao tempo de execução das duas versões. / 12

8 Média móvel A média móvel é muito utilizada em estatística e a motivação para essa seção surgiu de um estudo que estamos fazendo sobre a variação de preços de determinadas ações na bolsa de valores de São Paulo, onde calculamos o coeficiente correlacional (uma medida estatística que indica possíveis relações lineares entre variáveis aleatórias) entre essa medida e algumas outras variáveis. Suponha que temos um vetor de números reais (que chamaremos valores ) e um número inteiro representando um intervalo de interesse (que chamaremos janela ). O cálculo da média móvel consiste em calcular um novo vetor (que chamaremos resultados ) em que em cada posição i seja armazenado o valor da média aritmética das janelas posições anteriores a i do vetor valores. Por exemplo, considere o vetor valores mostrado na figura 3 e um valor de janela igual a 2. Figura 3. Vetor valores Neste caso, nosso vetor resultados consistiria dos valores mostrados na figura 4. Figura 4. Vetor resultados Como janela=2, não existem valores suficientes para o cálculo dos valores das duas primeiras posições do vetor resultados. A partir dali, cada posição contém a média aritmética das duas posições anteriores do vetor valores. Por exemplo, o valor 1.5 é a média aritmética dos valores 1 e 2. O valor 2.5 é a média aritmética dos valores 2 e 3. E assim por diante. O vetor resultados representa a média móvel dos valores contidos no vetor valores, para um intervalo de duas posições. Por simplicidade, em nossa implementação, as posições do vetor resultados para as quais não há dados suficientes para o cálculo serão mantidas vazias. Neste exemplo, além de calcular a média móvel, também vamos obter o valor máximo contido no vetor resultados. Fazemos isso com o intuito de ilustrar o uso da classe RecursiveTask, cujo método compute permite o retorno de um valor. Vamos implementar uma classe que chamaremos de MediaMovel. Essa classe contém as funcionalidades e dados que são comuns a ambas as implementações que faremos. Suas variáveis de instância são as seguintes. Dois vetores de double, um para os valores iniciais e outro para armazenar a média móvel. Duas variáveis inteiras, i e janela. A variável i representa o índice do vetor resultados para o qual desejamos calcular o valor. Ou seja, cada instância de MediaMovel será responsável pelo cálculo de uma das posições do vetor resultados. Organizamos o código dessa forma para tornar fácil a implementação da versão que utiliza a API Fork/Join. A classe MediaMovel com suas variáveis de instância aparece na Listagem 15. Listagem 15. A classe MediaMovel e suas variáveis de instância. class MediaMovel{ Double [] valores; Double [] resultados; int i; int janela; Além disso, a classe MediaMovel contém um método chamado calculamedia que faz o cálculo da média adequada para a posição i do vetor resultados. Sua implementação é mostrada na Listagem 16. Listagem 16. Implementação do método calculamedia. Seu objetivo é calcular o valor adequado para a posição i do vetor resultados e retornar esse valor. Double calculamedia(){ double resultado = 0; for (int j = i - 1; j >= i - janela; j--){ resultado += this.valores[j]; return (resultado / janela); Implementação simples Nesta seção mostramos uma possível implementação para o cálculo da média móvel. Esta implementação é puramente sequencial, não utilizamos processamento paralelo em momento algum. Na seção seguinte faremos uma implementação paralela utilizando a API Fork/Join para então comparar o tempo de execução de ambas. Criaremos uma classe chamada MediaMovelSerial que contém uma variável de instância do tipo MediaMovel e um método que chamamos calcula. Após o término do método calcula, o vetor resultados contém os valores que compõem a média móvel do vetor valores. Além disso, o método calcula retorna um valor real, que é o valor máximo contido no vetor resultados. Primeiramente calculamos o primeiro valor do vetor resultados e supomos que ele é o maior (afinal até então é o único). Usamos então um laço para calcular os valores restantes, atualizando o valor máximo até então a cada iteração, se necessário. Sua implementação é dada na Listagem 17. Listagem 17. A classe MediaMovelSerial faz uso de objetos da classe MediaMovel para fazer o cálculo de cada posição do vetor resultados. O cálculo de cada posição é feito em sequência, sem utilizar processamento paralelo. Ao final, o método calcula retorna o valor máximo contido no vetor de médias. 13 \

9 class MediaMovelSerial{ MediaMovel mediamovel; public Double calcula(){ Double maximo = this.mediamovel.calculamedia(); this.mediamovel.resultados[this. mediamovel.janela] = maximo; for (int k = this.mediamovel.janela + 1; k < this.mediamovel.resultados.length; k++){ this.mediamovel.resultados[k] = new MediaMovel(this.mediaMovel.valores,this.mediaMovel.resultados,k,this. mediamovel.janela).calculamedia(); maximo = Math.max(maximo, this.mediamovel.resultados[k]); return maximo; MediaMovelSerial(Double [] valores, Double [] resultados, int i, int janela){ this.mediamovel = new MediaMovel(valores, resultados, i, janela); Na Listagem 18 mostramos como um código cliente poderia fazer uso dessa classe. Ao final, verificamos quanto tempo em milissegundos demorou a execução. Listagem 18. Utilizando a classe MediaMovelSerial e verificando o tempo de execução para um vetor com valores aleatórios. public static void main(string[] args) { int janela = 2; Random random = new Random(); int n = 1000; Double [] valores = new Double[n]; for (int i = 0; i < n; i++){ valores[i] = random.nextdouble(); Double [] resultados = new Double[ valores.length + 1]; MediaMovelSerial m = new MediaMovelSerial(valores, resultados, janela, janela); long inicio = System.currentTimeMillis(); Double r = m.calcula(); long fim = System.currentTimeMillis(); System.out.println(fim - inicio); Implementação com Fork/Join Nesta seção, fazemos uso da classe MediaMovel desenvolvida para implementar um programa que calcula a média móvel de um conjunto de valores e retorna o valor máximo das médias, utilizando a API Fork/Join disponível a partir da versão 7 do Java. Para utilizar a API Fork/Join é interessante que se faça uma definição recursiva do problema que pretendemos resolver. Ou seja, como podemos definir o problema do cálculo da média móvel (e obtenção do valor máximo) em função de versões menores do mesmo problema. Vamos definir o problema da seguinte forma. Se a posição i do vetor de médias for a última posição do vetor, então quer dizer que basta fazer o cálculo da média móvel para esta posição e retornar o valor obtido, já que sendo o único ele deve ser o máximo. Caso contrário, precisamos calcular a média móvel da posição i e também do subvetor que começa no índice i+1 em diante. Utilizando esta estrutura desenvolveremos uma solução que submete ao pool de threads uma instância que resolve o problema para o subvetor [i+1..n] e devolve o valor máximo contido neste subvetor. Com este resultado em mãos, calculamos o valor para a posição i e verificamos qual o valor máximo, o valor na posição i ou o valor máximo contido no subvetor [i+1..n]. Escrevemos uma classe que chamaremos Media- MovelParalelo e que herda de RecursiveTask, pois desejamos submeter instâncias dessa classe a um ForkJoinPool e queremos obter um resultado ao final da execução. Nossa classe tem uma instância de MediaMovel e sobrescreve o método compute de RecursiveTask. No método compute, primeiro verificamos se o cálculo atual está sendo feito para a última posição do vetor de médias. Em caso positivo, simplesmente fazemos o cálculo, armazenando o valor obtido na posição adequada e retornamos esse mesmo valor. Caso contrário, criamos uma nova instância de MediaMovelParalelo que será submetida ao pool de threads, e deverá resolver o problema a partir do índice i + 1 do vetor de médias. A chamada m.fork() submete uma nova tarefa ao pool de threads. O método compute do objeto referenciado por m será eventualmente executado por uma das threads trabalhadoras do pool de threads. Essa chamada somente pode ser realizada por uma thread que pertença a um ForkJoin- Pool. É possível verificar isso se utilizando o método inforkjoinpool, herdado da classe RecursiveTask. A seguir, fazemos o cálculo para a posição i do vetor e finalmente fazemos uma chamada m.join(), que utilizamos para obter o resultado calculado pelo método compute do objeto referenciado por m. A chamada ao método join é bloqueante ela somente retorna uma vez que o método compute do objeto sobre o qual chamamos o método termina. Seu retorno é o valor calculado pelo método compute. Verificamos qual o valor maior aquele que calculamos para a posição i ou o valor máximo armazenado no subvetor[i+1..n] e retornamos esse valor. A Listagem 19 mostra a classe MediaMovelParalelo. Listagem 19. Implementação da classe MediaMovelParalelo que faz uso da API Fork/Join do Java 7 para resolver o problema utilizando processamento paralelo. / 14

10 class MediaMovelParalelo extends RecursiveTask<Double> { MediaMovel protected Double compute() { if (this.mediamovel.i == this.mediamovel. resultados.length - 1){ this.mediamovel.resultados[this.mediamovel.i] = this.mediamovel.calculamedia(); return this.mediamovel. resultados[this.mediamovel.i]; MediaMovelParalelo m = new MediaMovelParalelo( mediamovel.valores,mediamovel. resultados,mediamovel.i + 1, mediamovel.janela); m.fork(); this.mediamovel.resultados[this.mediamovel.i] = this.mediamovel.calculamedia(); return Math.max( this.mediamovel. resultados[this.mediamovel.i], m.join()); Para utilizar esta classe, vamos gerar um vetor com valores aleatórios e instanciar um ForkJoinPool para submeter uma instância de MediaMovelParalelo. Essa primeira instância recebe como valor i o próprio valor de janela, já que antes da primeira posição em que há uma média, existem janela posições para as quais não há dados suficientes para o cálculo. Calculamos também o tempo total gasto em milissegundos para a execução do programa. Este código de teste é mostrado na Listagem 20. Listagem 20. Testando a classe MediaMovelParalelo. public static void main(string[] args) { int janela = 2; Random random = new Random(); int n = 1000; Double [] valores = new Double[n]; for (int i = 0; i < n; i++){ valores[i] = random.nextdouble(); Double [] resultados = new Double[ valores.length + 1]; ForkJoinPool pool = new ForkJoinPool(); MediaMovelParalelo m = new MediaMovelParalelo( valores, resultados, janela,janela); long inicio = System.currentTimeMillis(); Double r = pool.invoke(m); long fim = System.currentTimeMillis(); System.out.println(fim inicio)); A chamada ao método invoke de ForkJoinPool é bloqueante. O valor final somente será atribuído à variável r em main depois que o cálculo tiver sido feito por completo. Problema 2: Conclusões A solução desenvolvida na seção anterior mostra o uso dos principais recursos da API Fork/Join. A classe RecursiveTask fornece um mecanismo que torna muito fácil a obtenção de resultados calculados por threads trabalhadoras de um ForkJoinPool. Apesar de teoricamente esperarmos um tempo de execução menor para a implementação utilizando processamento paralelo quando comparado com o tempo do programa sequencial, nossos resultados na prática mostraram sempre uma leve vantagem para a implementação sequencial. Isso está relacionado ao fato de não haver o que geralmente se chama de tail call optimization [3]. Assim, nossa solução tem como principal intuito demonstrar o uso da classe RecursiveTask. Observamos também o fato de a solução sequencial poder ser melhorada, pois tendo o valor da média móvel do vetor na posição i-1 em mãos, podemos utilizá-lo para o cálculo na posição i, sem a necessidade de fazer o cálculo completo. Considerações finais Com este artigo esperamos ter ilustrado o uso das principais classes do pacote java.util.concurrent. Em especial, esperamos ter tornado claro como a nova API Fork/Join do Java 7 pode ser usada para a solução de problemas para os quais encontramos uma definição recursiva. Quando desejamos submeter novas tarefas a partir de uma thread que pertence ao pool para o qual desejamos fazer a submissão, a implementação ForkJoinPool oferece mecanismos não presentes em versões anteriores ao Java 7, que tornam simples essa submissão. Nossos testes de desempenho mostram que nem sempre uma implementação paralela leva vantagem sobre uma implementação sequencial. Em um próximo artigo pretendemos estudar com mais detalhes o funcionamento do algoritmo de roubo de trabalho implementado pela classe ForkJoinPool. Como funciona esse roubo de trabalho? Será que as tarefas são pré-alocadas para as threads trabalhadoras? Será que uma thread muito ocupada tem mecanismos para decidir dividir seu trabalho e permitir que outras threads a ajudem? /referências > [1] CORMEN, Thomas H; LEISERSON, Charles E.; RIVEST, Ronald L.; STEIN, Clifford. Introduction to Algorithms. 3 ed. Massachusetts Institute of Technology, > [2] Oracle and/or its affiliates. Java Platform, Standard Edition Disponível em: < javase/7/docs/api/java/util/concurrent/package-summary. html>. Acesso em: 15 de Set. de > [3] Acesso em: 02 de out. de /agradecimentos > Agradeço à Luciene Rinaldi ([email protected]) pela sua valorosa ajuda ao revisar o trabalho. 15 \

Orientação a Objetos

Orientação a Objetos 1. Domínio e Aplicação Orientação a Objetos Um domínio é composto pelas entidades, informações e processos relacionados a um determinado contexto. Uma aplicação pode ser desenvolvida para automatizar ou

Leia mais

Introdução a Java. Hélder Nunes

Introdução a Java. Hélder Nunes Introdução a Java Hélder Nunes 2 Exercício de Fixação Os 4 elementos básicos da OO são os objetos, as classes, os atributos e os métodos. A orientação a objetos consiste em considerar os sistemas computacionais

Leia mais

Dadas a base e a altura de um triangulo, determinar sua área.

Dadas a base e a altura de um triangulo, determinar sua área. Disciplina Lógica de Programação Visual Ana Rita Dutra dos Santos Especialista em Novas Tecnologias aplicadas a Educação Mestranda em Informática aplicada a Educação [email protected] Conceitos Preliminares

Leia mais

Programação Orientada a Objetos Prof. Rone Ilídio UFSJ/CAP

Programação Orientada a Objetos Prof. Rone Ilídio UFSJ/CAP Programação Orientada a Objetos Prof. Rone Ilídio UFSJ/CAP 1) Introdução Programação Orientada a Objetos é um paradigma de programação bastante antigo. Entretanto somente nos últimos anos foi aceito realmente

Leia mais

ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo.

ARRAYS. Um array é um OBJETO que referencia (aponta) mais de um objeto ou armazena mais de um dado primitivo. Cursos: Análise, Ciência da Computação e Sistemas de Informação Programação I - Prof. Aníbal Notas de aula 8 ARRAYS Introdução Até agora, utilizamos variáveis individuais. Significa que uma variável objeto

Leia mais

Para criar uma animação precisamos de uma imagem e que ela contenha alguns frames. O número de frames é uma escolha sua.

Para criar uma animação precisamos de uma imagem e que ela contenha alguns frames. O número de frames é uma escolha sua. 7 Animação Animações é um dos quesitos muito importantes em jogos, você não acha? Para isso o JPlay tem uma classe específica para lidar com animações. Essa classe se chama Animation. Bem sugestivo o nome

Leia mais

CURSO DE PROGRAMAÇÃO EM JAVA

CURSO DE PROGRAMAÇÃO EM JAVA CURSO DE PROGRAMAÇÃO EM JAVA Introdução para Iniciantes Prof. M.Sc. Daniel Calife Índice 1 - A programação e a Linguagem Java. 1.1 1.2 1.3 1.4 Linguagens de Programação Java JDK IDE 2 - Criando o primeiro

Leia mais

THREADS EM JAVA. George Gomes Cabral

THREADS EM JAVA. George Gomes Cabral THREADS EM JAVA George Gomes Cabral THREADS Fluxo seqüencial de controle dentro de um processo. Suporte a múltiplas linhas de execução permite que múltiplos processamentos ocorram em "paralelo" (em computadores

Leia mais

Prototype, um Design Patterns de Criação

Prototype, um Design Patterns de Criação Prototype, um Design Patterns de Criação José Anízio Pantoja Maia Este artigo tem como finalidade compreender o funcionamento do padrão de projeto prototype, serão abordados os participantes que compõe

Leia mais

EXERCÍCIOS SOBRE ORIENTAÇÃO A OBJETOS

EXERCÍCIOS SOBRE ORIENTAÇÃO A OBJETOS Campus Cachoeiro de Itapemirim Curso Técnico em Informática Disciplina: Análise e Projeto de Sistemas Professor: Rafael Vargas Mesquita Este exercício deve ser manuscrito e entregue na próxima aula; Valor

Leia mais

Busca. Pesquisa sequencial

Busca. Pesquisa sequencial Busca Banco de dados existem para que, de tempos em tempos, um usuário possa localizar o dado de um registro, simplesmente digitando sua chave. Uma tabela ou um arquivo é um grupo de elementos, cada um

Leia mais

Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO)

Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO) Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO) Parte: 1 Prof. Cristóvão Cunha Objetivos de aprendizagem

Leia mais

Implementando uma Classe e Criando Objetos a partir dela

Implementando uma Classe e Criando Objetos a partir dela Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 04 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO) Parte: 2 Prof. Cristóvão Cunha Implementando uma Classe

Leia mais

Como foi exposto anteriormente, os processos podem ter mais de um fluxo de execução. Cada fluxo de execução é chamado de thread.

Como foi exposto anteriormente, os processos podem ter mais de um fluxo de execução. Cada fluxo de execução é chamado de thread. 5 THREADS Como foi exposto anteriormente, os processos podem ter mais de um fluxo de execução. Cada fluxo de execução é chamado de thread. 5.1 VISÃO GERAL Uma definição mais abrangente para threads é considerá-lo

Leia mais

2. Representação Numérica

2. Representação Numérica 2. Representação Numérica 2.1 Introdução A fim se realizarmos de maneira prática qualquer operação com números, nós precisamos representa-los em uma determinada base numérica. O que isso significa? Vamos

Leia mais

Programação Concorrente em java - Exercícios Práticos Abril 2004

Programação Concorrente em java - Exercícios Práticos Abril 2004 Programação Concorrente em java - Exercícios Práticos Abril 2004 1. Introdução As threads correspondem a linhas de controlo independentes no âmbito de um mesmo processo. No caso da linguagem JAVA, é precisamente

Leia mais

PROGRAMAÇÃO ORIENTADA A OBJETOS -TRATAMENTO DE EXCEÇÕES. Prof. Angelo Augusto Frozza, M.Sc. [email protected]

PROGRAMAÇÃO ORIENTADA A OBJETOS -TRATAMENTO DE EXCEÇÕES. Prof. Angelo Augusto Frozza, M.Sc. frozza@ifc-camboriu.edu.br PROGRAMAÇÃO ORIENTADA A OBJETOS -TRATAMENTO DE EXCEÇÕES Prof. Angelo Augusto Frozza, M.Sc. [email protected] ROTEIRO 5. Tratamento de Exceções Introdução e conceitos Capturando exceção usando

Leia mais

Desenvolvendo Websites com PHP

Desenvolvendo Websites com PHP Desenvolvendo Websites com PHP Aprenda a criar Websites dinâmicos e interativos com PHP e bancos de dados Juliano Niederauer 19 Capítulo 1 O que é o PHP? O PHP é uma das linguagens mais utilizadas na Web.

Leia mais

Notas da Aula 17 - Fundamentos de Sistemas Operacionais

Notas da Aula 17 - Fundamentos de Sistemas Operacionais Notas da Aula 17 - Fundamentos de Sistemas Operacionais 1. Gerenciamento de Memória: Introdução O gerenciamento de memória é provavelmente a tarefa mais complexa de um sistema operacional multiprogramado.

Leia mais

Manual AGENDA DE BACKUP

Manual AGENDA DE BACKUP Gemelo Backup Online DESKTOP Manual AGENDA DE BACKUP Realiza seus backups de maneira automática. Você só programa os dias e horas em que serão efetuados. A única coisa que você deve fazer é manter seu

Leia mais

Threads e Concorrência em Java (Material de Apoio)

Threads e Concorrência em Java (Material de Apoio) Introdução Threads e Concorrência em Java (Material de Apoio) Professor Lau Cheuk Lung http//www.inf.ufsc.br/~lau.lung INE-CTC-UFSC A maioria dos programas são escritos de modo seqüencial com um ponto

Leia mais

Estrutura de Dados Básica

Estrutura de Dados Básica Estrutura de Dados Básica Professor: Osvaldo Kotaro Takai. Aula 7: Recursividade O objetivo desta aula é apresentar o conceito de recursão para solução de problemas. A recursão é uma técnica de programação

Leia mais

Exercícios Teóricos Resolvidos

Exercícios Teóricos Resolvidos Universidade Federal de Minas Gerais Instituto de Ciências Exatas Departamento de Matemática Exercícios Teóricos Resolvidos O propósito deste texto é tentar mostrar aos alunos várias maneiras de raciocinar

Leia mais

Feature-Driven Development

Feature-Driven Development FDD Feature-Driven Development Descrição dos Processos Requisitos Concepção e Planejamento Mais forma que conteúdo Desenvolver um Modelo Abrangente Construir a Lista de Features Planejar por

Leia mais

Programação Orientada a Objetos Threads

Programação Orientada a Objetos Threads Threads Prof. Edwar Saliba Júnior Janeiro de 2013 1 Introdução Multithreading: fornece múltiplas threads de execução para a aplicação; permite que programas realizem tarefas concorrentemente; às vezes

Leia mais

Processos e Threads (partes I e II)

Processos e Threads (partes I e II) Processos e Threads (partes I e II) 1) O que é um processo? É qualquer aplicação executada no processador. Exe: Bloco de notas, ler um dado de um disco, mostrar um texto na tela. Um processo é um programa

Leia mais

Curso Adonai QUESTÕES Disciplina Linguagem JAVA

Curso Adonai QUESTÕES Disciplina Linguagem JAVA 1) Qual será o valor da string c, caso o programa rode com a seguinte linha de comando? > java Teste um dois tres public class Teste { public static void main(string[] args) { String a = args[0]; String

Leia mais

Algoritmos de Busca em Tabelas

Algoritmos de Busca em Tabelas Dentre os vários algoritmos fundamentais, os algoritmos de busca em tabelas estão entre os mais usados. Considere por exemplo um sistema de banco de dados. As operações de busca e recuperação dos dados

Leia mais

CONVENÇÃO DE CÓDIGO JAVA

CONVENÇÃO DE CÓDIGO JAVA CONVENÇÃO DE CÓDIGO JAVA Eligiane Ceron - Abril de 2012 Versão 1.0 Conteúdo Considerações iniciais... 2 Introdução... 2 Extensão de arquivos... 2 Arquivos de código Java... 2 Comentários iniciais... 2

Leia mais

Programação Concorrente em Java. Profa Andréa Schwertner Charão DLSC/CT/UFSM

Programação Concorrente em Java. Profa Andréa Schwertner Charão DLSC/CT/UFSM Programação Concorrente em Java Profa Andréa Schwertner Charão DLSC/CT/UFSM O que é programação concorrente? Um programa, múltiplos fluxos de execução Quando usar programação concorrente? Desempenho Ex.:

Leia mais

BACHARELADO EM SISTEMAS DE INFORMAÇÃO EaD UAB/UFSCar Sistemas de Informação - prof. Dr. Hélio Crestana Guardia

BACHARELADO EM SISTEMAS DE INFORMAÇÃO EaD UAB/UFSCar Sistemas de Informação - prof. Dr. Hélio Crestana Guardia O Sistema Operacional que você usa é multitasking? Por multitasking, entende-se a capacidade do SO de ter mais de um processos em execução ao mesmo tempo. É claro que, num dado instante, o número de processos

Leia mais

O ESPAÇO NULO DE A: RESOLVENDO AX = 0 3.2

O ESPAÇO NULO DE A: RESOLVENDO AX = 0 3.2 3.2 O Espaço Nulo de A: Resolvendo Ax = 0 11 O ESPAÇO NULO DE A: RESOLVENDO AX = 0 3.2 Esta seção trata do espaço de soluções para Ax = 0. A matriz A pode ser quadrada ou retangular. Uma solução imediata

Leia mais

Manual SAGe Versão 1.2 (a partir da versão 12.08.01)

Manual SAGe Versão 1.2 (a partir da versão 12.08.01) Manual SAGe Versão 1.2 (a partir da versão 12.08.01) Submissão de Relatórios Científicos Sumário Introdução... 2 Elaboração do Relatório Científico... 3 Submissão do Relatório Científico... 14 Operação

Leia mais

Parte I. Demoiselle Mail

Parte I. Demoiselle Mail Parte I. Demoiselle Mail Para o envio e recebimento de e-s em aplicativos Java, a solução mais natural é usar a API JavaMail [http:// www.oracle.com/technetwork/java/java/index.html]. Ela provê um framework

Leia mais

Entendendo como funciona o NAT

Entendendo como funciona o NAT Entendendo como funciona o NAT Vamos inicialmente entender exatamente qual a função do NAT e em que situações ele é indicado. O NAT surgiu como uma alternativa real para o problema de falta de endereços

Leia mais

Microsoft Access XP Módulo Um

Microsoft Access XP Módulo Um Microsoft Access XP Módulo Um Neste primeiro módulo de aula do curso completo de Access XP vamos nos dedicar ao estudo de alguns termos relacionados com banco de dados e as principais novidades do novo

Leia mais

Batalha Naval Algoritmos de Busca. Correlações curriculares Matemática: Números: maior que, menor que, iguais a.

Batalha Naval Algoritmos de Busca. Correlações curriculares Matemática: Números: maior que, menor que, iguais a. Atividade 6 Batalha Naval Algoritmos de Busca Sumário Computadores são freqüentemente requisitados a encontrar informação em grandes coleções de dados. Estes precisam desenvolver métodos rápidos e eficientes

Leia mais

ATRIBUTOS PRIVADOS 6. ENCAPSULAMENTO MÉTODOS PRIVADOS MÉTODOS PRIVADOS

ATRIBUTOS PRIVADOS 6. ENCAPSULAMENTO MÉTODOS PRIVADOS MÉTODOS PRIVADOS ATRIBUTOS PRIVADOS Podemos usar o modificador private, para tornar um atributo privado, obtendo um controle centralizado Definimos métodos para implementar todas as lógicas que utilizam ou modificam o

Leia mais

Memory Leak em Java?

Memory Leak em Java? 1 Memory Leak em Java? Saiba como memory leaks se manifestam em Java e como evitá-los Sobre o Autor Carlos Eduardo G. Tosin ([email protected]) é formado em Ciência da Computação pela PUC-PR, pós-graduado

Leia mais

Arquitetura de Rede de Computadores

Arquitetura de Rede de Computadores TCP/IP Roteamento Arquitetura de Rede de Prof. Pedro Neto Aracaju Sergipe - 2011 Ementa da Disciplina 4. Roteamento i. Máscara de Rede ii. Sub-Redes iii. Números Binários e Máscara de Sub-Rede iv. O Roteador

Leia mais

Módulo 07 Características Avançadas de Classes

Módulo 07 Características Avançadas de Classes Módulo 07 Características Avançadas de Classes Última Atualização: 15/06/2010 1 Objetivos Descrever variáveis, métodos e iniciadores static Descrever a semântica do modificador final em classes, métodos

Leia mais

Lógica de Programação

Lógica de Programação Lógica de Programação Unidade 20 ArrayList: Operações de Busca Curso Técnico em Informática SUMÁRIO INTRODUÇÃO... 3 TIPOS DE BUSCAS... 3 BUSCA ESPECÍFICA... 3 BUSCA ABRANGENTE... 3 PROCEDIMENTO DE BUSCA...

Leia mais

Aula 30 - Sockets em Java

Aula 30 - Sockets em Java Aula 30 - Sockets em Java Sockets Sockets são estruturas que permitem que funções de software se interconectem. O conceito é o mesmo de um soquete (elétrico, telefônico, etc...), que serve para interconectar

Leia mais

Tutorial de Matlab Francesco Franco

Tutorial de Matlab Francesco Franco Tutorial de Matlab Francesco Franco Matlab é um pacote de software que facilita a inserção de matrizes e vetores, além de facilitar a manipulação deles. A interface segue uma linguagem que é projetada

Leia mais

O Komunik é uma ferramenta de comunicação interna que permite a interação completa entre todos os setores de uma empresa.

O Komunik é uma ferramenta de comunicação interna que permite a interação completa entre todos os setores de uma empresa. ORG 13.8 KOMUNIK O QUE É Manual Estoque - Versão 4.55.001-2ª Edição - 2012 O Komunik é uma ferramenta de comunicação interna que permite a interação completa entre todos os setores de uma empresa. PRA

Leia mais

Manual AGENDA DE BACKUP

Manual AGENDA DE BACKUP Gemelo Backup Online DESKTOP Manual AGENDA DE BACKUP Realiza seus backups de maneira automática. Você só programa os dias e horas em que serão efetuados. A única coisa que você deve fazer é manter seu

Leia mais

AV2 - MA 12-2012. (a) De quantos modos diferentes posso empilhá-los de modo que todos os CDs de rock fiquem juntos?

AV2 - MA 12-2012. (a) De quantos modos diferentes posso empilhá-los de modo que todos os CDs de rock fiquem juntos? Questão 1. Num porta-cds, cabem 10 CDs colocados um sobre o outro, formando uma pilha vertical. Tenho 3 CDs de MPB, 5 de rock e 2 de música clássica. (a) De quantos modos diferentes posso empilhá-los de

Leia mais

Sistemas Operacionais Processos e Threads

Sistemas Operacionais Processos e Threads Sistemas Operacionais Processos e Threads Prof. Marcos Monteiro, MBA http://www.marcosmonteiro.com.br [email protected] 1 Estrutura de um Sistema Operacional 2 GERÊNCIA DE PROCESSOS Um processo

Leia mais

Processo de Controle das Reposições da loja

Processo de Controle das Reposições da loja Processo de Controle das Reposições da loja Getway 2015 Processo de Reposição de Mercadorias Manual Processo de Reposição de Mercadorias. O processo de reposição de mercadorias para o Profit foi definido

Leia mais

Reuso com Herança a e Composiçã

Reuso com Herança a e Composiçã Java 2 Standard Edition Reuso com Herança a e Composiçã ção Helder da Rocha www.argonavis.com.br 1 Como aumentar as chances de reuso Separar as partes que podem mudar das partes que não mudam. Exemplo:

Leia mais

Polimorfismo. Prof. Leonardo Barreto Campos 1

Polimorfismo. Prof. Leonardo Barreto Campos 1 Polimorfismo Prof. Leonardo Barreto Campos 1 Sumário Introdução; Polimorfismo; Polimorfismo Java; Métodos Abstratos Java Classes Abstratas Java Exercício - Java Polimorfismo C++ Classe Abstrata C++; Funções

Leia mais

SUMÁRIO 1. AULA 6 ENDEREÇAMENTO IP:... 2

SUMÁRIO 1. AULA 6 ENDEREÇAMENTO IP:... 2 SUMÁRIO 1. AULA 6 ENDEREÇAMENTO IP:... 2 1.1 Introdução... 2 1.2 Estrutura do IP... 3 1.3 Tipos de IP... 3 1.4 Classes de IP... 4 1.5 Máscara de Sub-Rede... 6 1.6 Atribuindo um IP ao computador... 7 2

Leia mais

ALGORITMOS DE ORDENAÇÃO. Algoritmos de comparação-e-troca. Bubble Sort Merge Sort Quick Sort

ALGORITMOS DE ORDENAÇÃO. Algoritmos de comparação-e-troca. Bubble Sort Merge Sort Quick Sort ALGORITMOS DE ORDENAÇÃO ALGORITMOS DE ORDENAÇÃO Algoritmos de comparação-e-troca Bubble Sort Merge Sort Quick Sort 1 BUBBLE SORT Usa a estratégia de comparação-e-troca É constituído por várias fases Cada

Leia mais

Armazenamento de Dados. Prof. Antonio Almeida de Barros Junior

Armazenamento de Dados. Prof. Antonio Almeida de Barros Junior Armazenamento de Dados Prof. Antonio Almeida de Barros Junior 1 Armazenamento de Dados Todos os dados que utilizamos até o momento, ficavam armazenados apenas na memória. Ao final da execução dos programas,

Leia mais

4 Segmentação. 4.1. Algoritmo proposto

4 Segmentação. 4.1. Algoritmo proposto 4 Segmentação Este capítulo apresenta primeiramente o algoritmo proposto para a segmentação do áudio em detalhes. Em seguida, são analisadas as inovações apresentadas. É importante mencionar que as mudanças

Leia mais

Sumário. 5COP096 Teoria da Computação Aula 8 Pesquisa em Memória Primária

Sumário. 5COP096 Teoria da Computação Aula 8 Pesquisa em Memória Primária 5COP096 Teoria da Computação Aula 8 Prof. Dr. Sylvio Barbon Junior Sylvio Barbon Jr [email protected] 1 Sumário 1) Introdução à Pesquisa em Memória Primária 2) Pesquisa Sequencial 3) Pesquisa Binária 4) Árvore

Leia mais

Para desenvolver a atividade a atividade desta aula utilizaremos o ambiente de desenvolvimento integrado NetBeans.

Para desenvolver a atividade a atividade desta aula utilizaremos o ambiente de desenvolvimento integrado NetBeans. 1 - Criando uma classe em Java Para desenvolver a atividade a atividade desta aula utilizaremos o ambiente de desenvolvimento integrado NetBeans. Antes de criarmos a(s) classe(s) é necessário criar o projeto

Leia mais

Resolução de problemas e desenvolvimento de algoritmos

Resolução de problemas e desenvolvimento de algoritmos SSC0101 - ICC1 Teórica Introdução à Ciência da Computação I Resolução de problemas e desenvolvimento de algoritmos Prof. Vanderlei Bonato Prof. Cláudio Fabiano Motta Toledo Sumário Análise e solução de

Leia mais

ISO/IEC 12207: Gerência de Configuração

ISO/IEC 12207: Gerência de Configuração ISO/IEC 12207: Gerência de Configuração Durante o processo de desenvolvimento de um software, é produzida uma grande quantidade de itens de informação que podem ser alterados durante o processo Para que

Leia mais

DEFINIÇÃO DE MÉTODOS

DEFINIÇÃO DE MÉTODOS Cursos: Análise, Ciência da Computação e Sistemas de Informação Programação I - Prof. Aníbal Notas de aula 2 DEFINIÇÃO DE MÉTODOS Todo o processamento que um programa Java faz está definido dentro dos

Leia mais

Itinerários de Ônibus Relatório Final

Itinerários de Ônibus Relatório Final CENTRO UNIVERSITÁRIO SENAC Itinerários de Ônibus Relatório Final Grupo 5 Caio Roque Daniel Nunes Elise Roese José Caneiro Marcos Grignani São Paulo Junho de 2007 1 ÍNDICE 1. Introdução... 3 2. Desenvolvimento...

Leia mais

Lógica de Programação

Lógica de Programação Lógica de Programação Softblue Logic IDE Guia de Instalação www.softblue.com.br Sumário 1 O Ensino da Lógica de Programação... 1 2 A Ferramenta... 1 3 Funcionalidades... 2 4 Instalação... 3 4.1 Windows...

Leia mais

Java para Desenvolvimento Web

Java para Desenvolvimento Web Java para Desenvolvimento Web Servlets A tecnologia Servlet foi introduzida pela Sun Microsystems em 1996, aprimorando e estendendo a funcionalidade e capacidade de servidores Web. Servlets é uma API para

Leia mais

Algoritmos e Programação (Prática) Profa. Andreza Leite [email protected]

Algoritmos e Programação (Prática) Profa. Andreza Leite andreza.leite@univasf.edu.br (Prática) Profa. Andreza Leite [email protected] Introdução O computador como ferramenta indispensável: Faz parte das nossas vidas; Por si só não faz nada de útil; Grande capacidade de resolução

Leia mais

Guia de Fatores de Qualidade de OO e Java

Guia de Fatores de Qualidade de OO e Java Qualiti Software Processes Guia de Fatores de Qualidade de OO e Java Versã o 1.0 Este documento só pode ser utilizado para fins educacionais, no Centro de Informática da Universidade Federal de Pernambuco.

Leia mais

Notas da Aula 4 - Fundamentos de Sistemas Operacionais

Notas da Aula 4 - Fundamentos de Sistemas Operacionais Notas da Aula 4 - Fundamentos de Sistemas Operacionais 1. Threads Threads são linhas de execução dentro de um processo. Quando um processo é criado, ele tem uma única linha de execução, ou thread. Esta

Leia mais

Relacionamentos entre objetos. Relacionamentos entre objetos. Relacionamentos entre objetos. Relacionamentos entre objetos

Relacionamentos entre objetos. Relacionamentos entre objetos. Relacionamentos entre objetos. Relacionamentos entre objetos Programação Orientada a Objetos Relacionamentos entre objetos Associação, composição e agregação Construtores e sobrecarga Variáveis de classe e de instância Reinaldo Gomes [email protected] Objetos

Leia mais

Especialização em desenvolvimento para web com interfaces ricas. Tratamento de exceções em Java Prof. Fabrízzio A. A. M. N. Soares

Especialização em desenvolvimento para web com interfaces ricas. Tratamento de exceções em Java Prof. Fabrízzio A. A. M. N. Soares Especialização em desenvolvimento para web com interfaces ricas Tratamento de exceções em Java Prof. Fabrízzio A. A. M. N. Soares Objetivos Conceito de exceções Tratar exceções pelo uso de try, catch e

Leia mais

A lógica de programação ajuda a facilitar o desenvolvimento dos futuros programas que você desenvolverá.

A lógica de programação ajuda a facilitar o desenvolvimento dos futuros programas que você desenvolverá. INTRODUÇÃO A lógica de programação é extremamente necessária para as pessoas que queiram trabalhar na área de programação, seja em qualquer linguagem de programação, como por exemplo: Pascal, Visual Basic,

Leia mais

A memória é um recurso fundamental e de extrema importância para a operação de qualquer Sistema Computacional; A memória trata-se de uma grande

A memória é um recurso fundamental e de extrema importância para a operação de qualquer Sistema Computacional; A memória trata-se de uma grande A memória é um recurso fundamental e de extrema importância para a operação de qualquer Sistema Computacional; A memória trata-se de uma grande região de armazenamento formada por bytes ou palavras, cada

Leia mais

O QUE É E COMO FUNCIONA O CREDIT SCORING PARTE I

O QUE É E COMO FUNCIONA O CREDIT SCORING PARTE I O QUE É E COMO FUNCIONA O CREDIT SCORING PARTE I! A utilização de escores na avaliação de crédito! Como montar um plano de amostragem para o credit scoring?! Como escolher as variáveis no modelo de credit

Leia mais

Java Básico. Classes Abstratas, Exceções e Interfaces Prof. Fernando Vanini Ic-Unicamp

Java Básico. Classes Abstratas, Exceções e Interfaces Prof. Fernando Vanini Ic-Unicamp Java Básico Classes Abstratas, Exceções e Interfaces Prof. Fernando Vanini Ic-Unicamp Classes Abstratas construção de uma classe abstrata construção de classes derivadas Classes e Herança Uma classe define

Leia mais

Capítulo 6. Criando um Diagrama de Caso de Uso Inicial

Capítulo 6. Criando um Diagrama de Caso de Uso Inicial Capítulo 6 Criando um Diagrama de Caso de Uso Inicial Mapa do Processo Por que Necessitamos de Um Diagrama de Casos de Uso? Eis algumas razões da necessidade de um Diagrama de Casos de Uso: O SRS é preenchido

Leia mais

Unidade 8: Padrão MVC e DAO Prof. Daniel Caetano

Unidade 8: Padrão MVC e DAO Prof. Daniel Caetano Programação Servidor para Sistemas Web 1 Unidade 8: Padrão MVC e DAO Prof. Daniel Caetano Objetivo: Apresentar a teoria por trás dos padrões na construção de aplicações Web. INTRODUÇÃO Nas aulas anteriores

Leia mais

Universidade da Beira Interior. Sistemas Distribuídos

Universidade da Beira Interior. Sistemas Distribuídos Folha 6-1 Sincronização de Threads A sincronização de Threads em Java é baseada no conceito do Monitor (de Hoare). Cada objecto Java tem associado um monitor (ou lock ) que pode ser activado se a palavra

Leia mais

O Princípio da Complementaridade e o papel do observador na Mecânica Quântica

O Princípio da Complementaridade e o papel do observador na Mecânica Quântica O Princípio da Complementaridade e o papel do observador na Mecânica Quântica A U L A 3 Metas da aula Descrever a experiência de interferência por uma fenda dupla com elétrons, na qual a trajetória destes

Leia mais

E A D - S I S T E M A S L I N E A R E S INTRODUÇÃO

E A D - S I S T E M A S L I N E A R E S INTRODUÇÃO E A D - S I S T E M A S L I N E A R E S INTRODUÇÃO Dizemos que uma equação é linear, ou de primeiro grau, em certa incógnita, se o maior expoente desta variável for igual a um. Ela será quadrática, ou

Leia mais

Especificação do 3º Trabalho

Especificação do 3º Trabalho Especificação do 3º Trabalho I. Introdução O objetivo deste trabalho é abordar a prática da programação orientada a objetos usando a linguagem Java envolvendo os conceitos de classe, objeto, associação,

Leia mais

5.1 Exemplos de uso Mediante a instanciação de componentes específicos, o OiL pode ser configurado

5.1 Exemplos de uso Mediante a instanciação de componentes específicos, o OiL pode ser configurado 5 Avaliação Decidimos avaliar a arquitetura de componentes para o OiL proposta neste trabalho em duas dimensões diferentes. Na primeira, demonstramos a capacidade de configuração do middleware com alguns

Leia mais

Linguagem de Programação JAVA. Técnico em Informática Professora Michelle Nery

Linguagem de Programação JAVA. Técnico em Informática Professora Michelle Nery Linguagem de Programação JAVA Técnico em Informática Professora Michelle Nery Agenda Regras paravariáveis Identificadores Válidos Convenção de Nomenclatura Palavras-chaves em Java Tipos de Variáveis em

Leia mais

1. Avaliação de impacto de programas sociais: por que, para que e quando fazer? (Cap. 1 do livro) 2. Estatística e Planilhas Eletrônicas 3.

1. Avaliação de impacto de programas sociais: por que, para que e quando fazer? (Cap. 1 do livro) 2. Estatística e Planilhas Eletrônicas 3. 1 1. Avaliação de impacto de programas sociais: por que, para que e quando fazer? (Cap. 1 do livro) 2. Estatística e Planilhas Eletrônicas 3. Modelo de Resultados Potenciais e Aleatorização (Cap. 2 e 3

Leia mais

Software. Gerenciamento de Manutenção

Software. Gerenciamento de Manutenção Software Gerenciamento de Manutenção Tutorial Passo a Passo Do Cadastro de Serviço à Consulta de Serviços Realizados Tutorial Recomendações AsinformaçõesutilizadasnestetutorialsãoasmesmasquevocêtemnoseuBancodeDados

Leia mais

Modelo Cascata ou Clássico

Modelo Cascata ou Clássico Modelo Cascata ou Clássico INTRODUÇÃO O modelo clássico ou cascata, que também é conhecido por abordagem top-down, foi proposto por Royce em 1970. Até meados da década de 1980 foi o único modelo com aceitação

Leia mais

10 DICAS DE TECNOLOGIA PARA AUMENTAR SUA PRODUTIVIDADE NO TRABALHO

10 DICAS DE TECNOLOGIA PARA AUMENTAR SUA PRODUTIVIDADE NO TRABALHO 10 DICAS DE TECNOLOGIA PARA AUMENTAR SUA PRODUTIVIDADE NO TRABALHO UMA DAS GRANDES FUNÇÕES DA TECNOLOGIA É A DE FACILITAR A VIDA DO HOMEM, SEJA NA VIDA PESSOAL OU CORPORATIVA. ATRAVÉS DELA, ELE CONSEGUE

Leia mais

Manual de Atualização Versão 3.6.4.

Manual de Atualização Versão 3.6.4. Manual de Atualização Versão 3.6.4. Sumário 1. AVISO... 1 2. INTRODUÇÃO... 2 3. PREPARAÇÃO PARA ATUALIZAÇÃO... 3 4. ATUALIZANDO GVCOLLEGE E BASE DE DADOS... 7 5. HABILITANDO NOVAS VERSÕES DO SISTEMA....

Leia mais

CAPÍTULO 3 - TIPOS DE DADOS E IDENTIFICADORES

CAPÍTULO 3 - TIPOS DE DADOS E IDENTIFICADORES CAPÍTULO 3 - TIPOS DE DADOS E IDENTIFICADORES 3.1 - IDENTIFICADORES Os objetos que usamos no nosso algoritmo são uma representação simbólica de um valor de dado. Assim, quando executamos a seguinte instrução:

Leia mais

Profº. Enrique Pimentel Leite de Oliveira

Profº. Enrique Pimentel Leite de Oliveira Profº. Enrique Pimentel Leite de Oliveira O termo orientação a objetos significa organizar o mundo real como uma coleção de objetos que incorporam estrutura de dados e um conjunto de operações que manipulam

Leia mais

PROGRAMAÇÃO ESTRUTURADA. CC 2º Período

PROGRAMAÇÃO ESTRUTURADA. CC 2º Período PROGRAMAÇÃO ESTRUTURADA CC 2º Período PROGRAMAÇÃO ESTRUTURADA Aula 07: Funções O comando return Protótipo de funções O tipo void Arquivos-cabeçalho Escopo de variáveis Passagem de parâmetros por valor

Leia mais

Java 2 Standard Edition Como criar classes e objetos

Java 2 Standard Edition Como criar classes e objetos Java 2 Standard Edition Como criar classes e objetos Helder da Rocha www.argonavis.com.br 1 Assuntos abordados Este módulo explora detalhes da construção de classes e objetos Construtores Implicações da

Leia mais

PROCEDIMENTOS PARA CONVERSÃO DE IMAGENS DIGITALIZADAS EM DOCUMENTO PDF ÚNICO UTILIZANDO A IMPRESSORA FREEPDF XP.

PROCEDIMENTOS PARA CONVERSÃO DE IMAGENS DIGITALIZADAS EM DOCUMENTO PDF ÚNICO UTILIZANDO A IMPRESSORA FREEPDF XP. PROCEDIMENTOS PARA CONVERSÃO DE IMAGENS DIGITALIZADAS EM DOCUMENTO PDF ÚNICO UTILIZANDO A IMPRESSORA FREEPDF XP. O objetivo deste manual é orientar os usuários do sistema de Processo Eletrônico a transformar

Leia mais

Exercícios de Revisão Java Básico

Exercícios de Revisão Java Básico Exercícios de Revisão Java Básico (i) Programação básica (estruturada) 1) Faça um programa para calcular o valor das seguintes expressões: S 1 = 1 1 3 2 5 3 7 99... 4 50 S 2 = 21 50 22 49 23 48...250 1

Leia mais

FATEC Cruzeiro José da Silva. Ferramenta CRM como estratégia de negócios

FATEC Cruzeiro José da Silva. Ferramenta CRM como estratégia de negócios FATEC Cruzeiro José da Silva Ferramenta CRM como estratégia de negócios Cruzeiro SP 2008 FATEC Cruzeiro José da Silva Ferramenta CRM como estratégia de negócios Projeto de trabalho de formatura como requisito

Leia mais

Engenharia de Software III

Engenharia de Software III Engenharia de Software III Casos de uso http://dl.dropbox.com/u/3025380/es3/aula6.pdf ([email protected]) 09/09/2010 O que são casos de uso? Um caso de uso procura documentar as ações necessárias,

Leia mais

Resolução da lista de exercícios de casos de uso

Resolução da lista de exercícios de casos de uso Resolução da lista de exercícios de casos de uso 1. Explique quando são criados e utilizados os diagramas de casos de uso no processo de desenvolvimento incremental e iterativo. Na fase de concepção se

Leia mais

AULA 5 Sistemas Operacionais

AULA 5 Sistemas Operacionais AULA 5 Sistemas Operacionais Disciplina: Introdução à Informática Professora: Gustavo Leitão Email: [email protected] Sistemas Operacionais Conteúdo: Partições Formatação Fragmentação Gerenciamento

Leia mais

UML Aspectos de projetos em Diagramas de classes

UML Aspectos de projetos em Diagramas de classes UML Aspectos de projetos em Diagramas de classes Após ser definido o contexto da aplicação a ser gerada. Devemos pensar em detalhar o Diagrama de Classes com informações visando uma implementação Orientada

Leia mais

Aula 4 Estatística Conceitos básicos

Aula 4 Estatística Conceitos básicos Aula 4 Estatística Conceitos básicos Plano de Aula Amostra e universo Média Variância / desvio-padrão / erro-padrão Intervalo de confiança Teste de hipótese Amostra e Universo A estatística nos ajuda a

Leia mais