Paralelismo. e Performance. Desenvolva código paralelo de forma simples mensurando ganhos reais em performance.

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

Download "Paralelismo. e Performance. Desenvolva código paralelo de forma simples mensurando ganhos reais em performance."

Transcrição

1 capa_ Paralelismo e Performance em Java Desenvolva código paralelo de forma simples mensurando ganhos reais em performance. Escrever código para processamento em paralelo é algo que, muitas vezes, mistura mágica e polêmica. Erros devido à falta de sincronização normalmente não são fáceis de descobrir ou tão pouco reproduzir. Este artigo tem como objetivo eliminar a mágica e a polêmica com relação a este assunto. Eliminar a mágica no sentido de mensurar o comportamento do código, seja ele sequencial ou paralelo. E eliminar a polêmica no sentido de escrever código com comportamento seguro e previsível. processamento paralelo faz parte do dia-a-dia O de desenvolvedores, sem que isso esteja explícito. Afinal de contas, até uma simples aplicação web possui um ThreadPool implementado pelo servidor de aplicação, por exemplo. Em muitos casos, não é necessário entender os mecanismos ou boas práticas do processamento paralelo, graças ao bom trabalho de abstração e arquitetura feito no desenvolvimento de servidores de aplicação e frameworks. Muitas vezes existe a oportunidade de paralelizar algum processamento, mas não é conveniente fazer pelo simples fato de manter a arquitetura simples para não introduzir erros ou complexidades no código. A infraestrutura de servidores de aplicação muitas vezes consegue deixar algo que foi desenvolvido para processamento sequencial em uma velocidade satisfatória. O fato é: existem diversos motivos para não se preocupar com código para processamento paralelo ou programação Multi-threaded. Algumas vezes porém, é necessário enfrentar cenários diferentes destes citados, onde o desenvolvedor deve melhorar performance de algo que já tenha sido otimizado ao máximo. As opções de servidores mais robustos já se esgotaram, tal como simplificar / 16

2 Luiz Fernando Teston Possui mais de 12 anos de experiência em desenvolvimento de software não trivial. Neste tempo já desenvolveu plugins para Eclipse, analisadores de código, sistemas de alta performance em Java e C++, dentre outros. Já palestrou em eventos como TDC, NoSQL:BR, JustJava e JavaOne São Paulo. Atualmente é engenheiro de Software Sênior no campus de desenvolvimento da Ericsson Irlanda. as regras de negócio. A fila para agendamento de processamentos a noite já está cheia. Para otimizar qualquer código existente ou para preparar código novo, normalmente o programador faz deduções como: Com certeza determinada parte é o problema. Após horas de trabalho é possível que não tenha havido nenhuma melhoria sequer, ou pior ainda, que o código esteja com novas falhas ou mesmo com um tempo de processamento maior. Este artigo propõe abordagens concisas para abordar este tipo de problema, como, por exemplo, medir qual o tempo do gargalo que está ocorrendo e descobrir onde está ocorrendo este mesmo gargalo. Da mesma forma, é necessário obter medições da melhoria, para que a instalação em produção seja feita de forma confiável e sem nenhum receio por parte do autor da alteração. Para fazer estas medições existem técnicas e ferramentas, tais como medidores de performance ou Profillers, desenvolvimento de testes unitários e integrados, logs e outras abordagens do gênero. Após medir e isolar o determinado trecho do código a ser otimizado, utilizando orientação a objetos é possível desenvolver um código novo seguindo a interface do código legado sequencial, e isolar o processamento paralelo. Desta forma, torna- -se simples efetuar testes e medições em cenários novos e antigos. Utilizando esta abordagem, é possível se preparar para diversos problemas que se enfrenta no dia-a-dia de desenvolvimento de software, argumentando que determinada alteração trouxe melhorias com evidências claras ou mesmo se preparar para a troca de código trocando-se apenas as implementações. Este tipo de atividade não precisa ser complicada e muito menos chata ou desgastante. De fato, isto pode ser divertido e gratificante principalmente ao se deparar com resultados satisfatórios e, por consequência, elogios de outros programadores e pessoas da área. Vamos ao que interessa! Entendendo e visualizando paralelismo e concorrência Antes de começar a praticar, é necessário entender alguns conceitos. Provavelmente os conceitos iniciais explicados aqui serão familiares, mas algumas vezes o entendimento de alguns destes conceitos é vago. A explicação acadêmica nem sempre é simples de entender para muitos. Nem sempre se entende problemas como Barbeiro dorminhoco ou Jantar dos filósofos já na primeira leitura, embora não sejam problemas realmente complexos. O primeiro conceito a ser definido é o conceito de linha de execução, ou thread. Uma thread, desde que não esteja disputando nenhum recurso, processa de forma independente instruções de um programa. Em se tratando de Java, quando executamos o método main, haverá uma thread para a execução deste método. Internamente existe um agendador coordenando a execução das threads, dividindo o tempo disponível dos processadores entre as várias threads que precisem ser executadas. De certa forma, é possível pensar em uma disputa existente entre as threads pelo tempo disponível dos processadores. Em um cenário hipotético, onde existe somente um núcleo do processador disponível para processar mais de uma thread, esta disputa pelo processador certamente ocorrerá. Para existir a aparência de executar todas estas threads ao mesmo tempo será necessário dividir o tempo do processador em fatias de tempo, e ceder cada uma destas fatias para todas as threads em um momento diferente. Não ocorre execução em paralelo, pois somente uma thread está executando em um dado momento, mas conforme passa o tempo, a aparência é que todas as threads estão executando. Em um cenário como este, dizemos que a execução é feita de forma concorrente. A execução somente será feita em paralelo em casos onde não ocorrem nenhuma disputa sequer, seja pelo processador ou seja por outros recursos. É possível ver a diferença entre paralelismo e concorrência ao ver gráficos de monitores de performance ou profillers, como, por exemplo, o Visual VM. O Visual VM é um programa de monitoração (ou profiller) disponibilizado pela Oracle. Ele é bastante simples de usar. Na figura 1 temos um exemplo de disputa por recursos, onde é possível ver no gráfico de execução das threads, algumas threads nomeadas por disputer 1, 2 e 3. Temos pedaços em vermelho, mostrando a thread parada devido à disputa por algum recurso, pedaços em verde, mostrando a thread sendo executada, e pedaços em roxo, mostrando a thread em estado sleeping. Utilizar um profiller quando se programa esperando paralelismo é algo extremamente recomendável. Na imagem citada, não temos um resultado satisfatório no uso de paralelismo. Isto somente fica claro no uso do profiller 17 \

3 durante a execução. O profiller tira fotos de como está a execução das threads de tempos em tempos e monta o gráfico. Assim ele não interfere na execução de forma a atrapalhar de forma sensível a execução. E isto é um dos fatores que diferenciam os profillers existentes no mercado. uma frase por vez ao invés de uma letra por vez, ou uma palavra por vez, por exemplo. Na figura 2, é possível ver um exemplo onde se pode escrever uma palavra por vez ou uma frase por vez. Em um dos exemplos a monitoração da escrita é feita de forma correta, e em outra não. O exemplo aqui mostra de forma bem clara que em um dos casos o estado do conteúdo do chat fica inconsistente. O mesmo ocorre se considerarmos duas threads de um mesmo programa tentando a escrita ao mesmo tempo em um arquivo. thread 1 Obter e incrementar 1+1=2 thread 2 Obter e incrementar 1+1=2 Figura 1. Execução de threads monitoradas pelo Oracle Visual VM. A disputa por recursos Além do processador, existe uma série de outros itens que são alvo de disputa. Em se tratando de recursos computacionais, pode existir disputas por leitura e escrita de arquivos, comunicação de rede, recursos de um banco de dados e itens afins. Tudo o que pode ser acessado ao mesmo tempo precisa ser monitorado para que não fique em estado inconsistente. Para que uma thread possa utilizar um recurso monitorado, existem algumas formas de sincronizar este acesso. Isto se dá ao uso de travas ou locks. Em Java, existem algumas formas de fazer isso, como, por exemplo, o uso da palavra-chave synchronized, ou o uso de classe para locking da API de concorrência do Java. O objetivo é o mesmo: garantir que apenas uma thread irá utilizar um recurso por vez. Caso um recurso já esteja sendo utilizado por outra thread, a thread que solicita o recurso irá ficar aguardando este mesmo recurso estar disponível. Falando de forma mais simples, cada thread terá a sua vez de usar um recurso. Como você está? Tudo bem! E você? Tudo bem também. sincronização APROPRIADA sincronização não apropriada Figura 2. Sincronização em um chat. 1.Como você está? 2. Tudo bem! E você? 3. Tudo bem também. Como você Tudo está bem! E Tudo bem você? também. Utilizando o cenário onde temos a escrita de frases em um chat existe um texto comum que deve ser exibido para todos. O ideal é que seja escrita apenas Total MOMENTO inicial: ESTADO consistente 1 Total 2 momento final: ESTADO inconsistente Figura 3. Falta de sincronização em um contador de acessos. thread 1 thread 2 MOMENTO inicial: ESTADO consistente Obter e incrementar 1+1=2 Obter e incrementar Total 1 Total 2 Total 3 1+1=2 momento final: ESTADO consistente Figura 4. Sincronização correta em um contador de acessos. Na figura 3, temos outro exemplo do que a falta de um lock pode fazer em termos de produzir um estado inconsistente, onde um contador com valor 1 ao ser incrementado duas vezes deveria ter um valor final 3 e não 2. Isto não teria acontecido se houvesse o uso correto de um lock permitindo que somente uma thread pudesse obter e alterar o valor da variável do contador por vez. Basicamente, nos casos de disputa de recursos, para mantermos um estado consistente, é necessário que este recurso esteja com apenas uma thread o modificando por vez. É possível enumerar inúmeros exemplos de estado inconsistente devido à falta de sincronização para mostrar a necessidade do uso de locks. / 18

4 Cuidados ao utilizar locks Em alguns momentos pode ser necessário usar mais de um lock, como, por exemplo, em um cenário onde existe uma movimentação bancária entre duas contas. A operação de retirada de uma das contas precisa ser sincronizada com a operação de entrada na conta que recebe o dinheiro da transferência. Este tipo de problema de sincronização já foi resolvido por muitos bancos de dados, e é um problema difícil de ser resolvido. Pense por um momento na dificuldade de resolver este problema. Por exemplo, utilizar somente um lock para proteger todas as contas seria inviável, dado o número elevado de contas bancárias. Outra solução é utilizar um lock por conta bancária. Em cada operação de transferência, seriam adquiridos os locks de cada uma das contas bancárias envolvidas na movimentação, e então, somente após a aquisição de todos os locks das contas envolvidas, seria possível efetuar a movimentação. efetuar a movimentação bancária, terminando por devolver o lock da conta B e, em seguida, devolver o lock da conta A. Na segunda movimentação a lógica é a mesma, mas em ordem diferente. Em um dado momento a primeira thread terá adquirido o lock da conta A, e estará aguardando o lock da conta B enquanto a segunda thread terá adquirido o lock da conta B e estará aguardando o lock da conta A. Neste cenário, ambas estarão esperando eternamente, consumindo ciclos de processamento e, em muitas vezes, travando a aplicação envolvida. Thread 1 Lock Thread 1 Thread 1 A Lock Lock Lock A B A Thread 2 Lock Thread 2 Thread 2 B Lock Lock Lock B A B Conta bancária A Saldo: R$ Conta bancária A Saldo: R$ Conta bancária A Saldo: R$ momento inicial: ambas as threads estão EXECUTANDO e nenhuma delas adquiriu algum lock ambas as threads adquirem seu RESPECTIVO lock em ordem diferente momento final: ambas as threads estão esperando um lock já adquirido Conta bancária B Saldo: R$ momento inicial: CONTAS disponíveis PARA movimentação Transferência Conta A > Conta B R$ Conta bancária B Saldo: R$ MOMENTO intermediário: lock das duas contas PARA movimentação Conta bancária B Saldo: R$ MOMENTO final: CONTAS disponíveis PARA movimentação em ESTADO consistente Figura 5. Exemplo do uso de locks em movimentação de contas bancárias. No entanto, em um cenário onde temos mais de um lock envolvido, existe a possibilidade de que ocorra um dead lock. Dead lock é o nome dado quando temos dois ou mais recursos sendo usados e ao mesmo tempo aguardado por duas ou mais threads envolvidas. É difícil resumir em apenas uma frase como funciona um dead lock de forma clara. Cada lock envolvido é adquirido por uma thread de forma atômica. Sendo assim, para adquirir dois locks, é necessário adquirir um por vez. Utilizando o exemplo da conta bancária, iremos efetuar uma movimentação da conta A para a conta B, e ao mesmo tempo uma movimentação da conta B para a conta A. Os passos envolvidos na primeira movimentação são adquirir o lock da conta A, adquirir o lock da conta B, e então Figura 6. Exemplo de dead lock. Existem algumas formas simples de se evitar dead locks. A primeira delas é simplesmente utilizar um lock para toda a aplicação. Nesta abordagem, o paralelismo é sacrificado a cada vez que ocorre disputa pelo lock global na aplicação. Outra forma é garantir a ordem de aquisição dos locks. Isto é bastante difícil, pois, na maior parte dos casos, as aplicações em que ocorrem processamentos em paralelo possuem um código bastante grande e complexo. Uma terceira forma de se evitar dead locks, é evitando a disputa por recursos. A disputa por recursos sempre vai ocorrer de uma forma ou de outra, mas é interessante pelo menos minimizar ao máximo a disputa por recursos, pois assim se minimiza o risco durante a execução. Heisenbugs Em física quântica existe o chamado princípio da incerteza de Heisenberg, que diz que, ao observar um experimento, ele é alterado. Explicado de forma excessivamente simplista, em física quântica, isto ocorre pois o universo quântico é sensível a interferências, inclusive de detectores e microscópios eletrônicos, por exemplo. Agora, tomemos como ambiente não o universo quântico, mas o sistema o qual ocorre um processamento em paralelo em um computador. Para observar o que acontece é necessário interferir no sistema, seja imprimindo uma mensagem de log em 19 \

5 um arquivo ou na tela, seja parando a execução durante uma sessão de depuração ou debug. Repare que todos os itens citados mudam algum estado. Ou seja, qualquer forma de observar um programa em execução constitui em se ter alguma alteração de estado ou side effect (será definido adiante). Os side effects neste caso podem mudar a ordem de aquisição dos locks, por exemplo. Ao ativar um log, efetuar um debug ou mesmo ao se trocar o ambiente de execução podemos ter como resultado uma alteração na ordem de aquisição de locks. Um dead lock ou erro que só acontece em produção pode deixar de acontecer em desenvolvimento, em debug ou mesmo em uma nova execução. Estes erros, que tiram o sono de muitos programadores, podem ficar por muito tempo sem se manifestar e/ou só se manifestar em determinadas condições. São conhecidos por heisenbugs. Não é necessário o uso de locks para se ter um heisenbug. A falta de locking ou sincronismo introduz comportamento inesperado e é ainda mais perigosa. A melhor forma de se evitar heisenbugs é ter um código que não faça uso abusivo de locks, mas que nem por isso deixe de ser seguro. E uma forma simples de fazer isso é utilizar a abordagem funcional durante o paralelismo. A abordagem funcional Programação funcional é um assunto que está voltando ao foco aos poucos com linguagens como Scala, Erlang ou Clojure. Mas o fato é que muitos dos conceitos importantes de programação funcional podem ser utilizados em qualquer linguagem. O fato de Java ser orientada a objetos significa que a linguagem foi projetada tendo orientação a objetos em mente, não impedindo de se utilizar Java de forma funcional. De fato, algumas práticas de programação funcional, como, por exemplo, imutabilidade de objetos, são até citadas como boas práticas em Java no livro Effective Java, de Joshua Bloch. Um dos conceitos de programação funcional mais importantes que existem, é o conceito de efeitos colaterais ou side effects. Ocorrem side effects quando uma função ou trecho de um programa modifica algum estado de qualquer elemento, seja ele interno ou externo. Alguns exemplos de side effects são, por exemplo, uma movimentação bancária, gravar dados em um arquivo, escrever algo no banco de dados, mudar uma data do sistema, mudar um atributo de algum objeto. De fato, até imprimir um hello world na tela implica em se ter um side effect. Side effects na maior parte dos casos significa um ponto onde pode ocorrer disputa. O interessante aqui é que muitas ações triviais feitas no dia-a-dia de desenvolvimento implicam em existir side effects durante sua execução. O paradigma de programação funcional possui este nome por ter muito a ver com funções matemáticas. Por definição, a função pura em programação funcional não pode depender de nenhum estado interno ou externo em sua execução e, muito menos, pode alterar qualquer estado, interno ou externo. Por exemplo, uma função pura não pode alterar a data do sistema e nem pode depender desta data. Também não pode alterar estado de objetos ou tão pouco ler ou salvar algo no banco de dados. Funções puras são parecidas com funções matemáticas, onde se recebe parâmetros e se devolve um resultado, não sendo feito nada além disso. Funções matemáticas como seno, cosseno, tangente, soma, subtração etc. são funções puras. O mais interessante, no que diz respeito a funções puras, é o fato de que, ao utilizá-las, é possível obter paralelismo. Estas funções não adquirem nem modificam recursos externos, e por isso não necessitam do uso de locks. Isolando um código em partes puras e impuras é possível saber onde podem ocorrer dead locks no código. Basicamente, a forma de trabalhar em paralelo, proposta neste artigo, é não depender de estado interno ou externo durante a execução em paralelo. Pode parecer contraditório falar de programação funcional em uma linguagem orientada a objetos, afinal de contas, objetos guardam e modificam estado interno o tempo todo. A questão aqui não é deixar de usar orientação a objetos, mas sim utilizar da forma que melhor convém cada uma de suas características. A forma de trabalhar com objetos de forma funcional é utilizar objetos imutáveis, tanto como argumento quanto como resultado de métodos. Esta abordagem é utilizada em Java em muitas classes do dia-a-dia, como, por exemplo, as classes String, wrappers em geral, como BigDecimal, Integer ou Double. Examine por um momento um dos métodos matemáticos da classe BigDecimal. Estes métodos não modificam o estado interno de seu objeto, mas sim retornam um BigDecimal novo com o resultado. A mesma abordagem pode ser feita de forma simples em seus objetos de negócio que precisem ser paralelizados. Faça uma classe com atributos marcados como final, implemente seus métodos que iriam modificar o estado interno retornando valores novos, e já existe a garantia que as lógicas de negócio de sua classe podem ser chamadas em paralelo sem maiores preocupações. O mais interessante é que ao trabalhar com objetos imutáveis, mesmo sem envolver chamadas em paralelo, a segurança no código aumenta. Verifique que nem por acidente é possível alterar o valor de uma variável (constante) compartilhada. Listagem 1. Exemplo de segurança no código com a abordagem funcional. BigDecimal bd = BigDecimal.TEN; // A chamada abaixo retorna um novo objeto de valor 20, / 20

6 // que é descartado. A constante BigDecimal.TEN não foi // alterada nem por acidente BigDecimal.TEN.add(BigDecimal.TEN); Encontrando o gargalo Muitas vezes o programador se depara com um problema de performance em um código desconhecido. Um cenário comum é um programador iniciando em uma empresa como funcionário novo, herdando o projeto cujo autor não trabalha mais na empresa. Um funcionário antigo também poderá ser acionado para descobrir o que está acontecendo em determinada aplicação em produção, sendo ele o autor da aplicação ou não. Existem diversas formas de proceder nestes cenários. Todas as formas podem ser convenientes, ou não, dependendo do cenário. Um código conhecido na maior parte dos casos não exigirá tanta investigação quanto um código desconhecido para entendimento do mesmo. Ler o código para procurar o gargalo é a primeira coisa que se faz na maioria dos casos, muitas vezes por instinto. Este procedimento para entendimento de sua execução é algo totalmente válido, mas o esforço em procurar gargalos lendo o código poucas vezes tem resultado satisfatório, principalmente se o gargalo não for trivial. Esta abordagem em pouco tempo se transforma em tentativa e erro. Para apontar suspeitos pelo problema de performance apenas por suposição, se esta for a única forma, os principais suspeitos terão alguma comunicação externa envolvida, seja ela leitura e escrita em arquivos, rede ou comunicação com banco de dados. Cláusulas SQL que não utilizam índices de forma apropriada ou que trafegam mais dados do que deveriam são comuns, assim como transações em banco de dados que duram mais tempo do que o necessário, travando registros que precisem ser utilizados por outras transações. // abordagem funcional para obter um resultado bd = bd.add(bigdecimal.ten); Lembrando que, para uma classe ser imutável, seus campos precisam ser imutáveis ou pelo menos protegidos de alteração externa. Uma das técnicas para proteger um campo mutável de alteração é retornar uma cópia deste campo em seu método getter. Caso uma classe imutável tenha um número excessivo de argumentos em seu construtor, é possível passar um objeto de parâmetros mutável em seu construtor, ou utilizar o design pattern builder conforme descrito no livro Effective Java. Pode parecer burocrático ter uma classe a mais apenas para poder auxiliar na criação de uma nova instância imutável, mas pense nas vantagens. Objetos imutáveis não precisam de proteção. Podem ser passados como argumento para execuções em paralelos sem necessitar de locking. Isto, por si só, já previne dead locks, simplifica e deixa o código robusto, previsível e, principalmente, simples. Figura 7. Profiller exibindo tempo gasto por métodos. Nos casos onde temos comunicação externa como um possível vilão, o uso de escrita em arquivos de logs mostrando o tempo gasto nestas operações se trata de uma ferramenta útil. Existe a introdução de um side effect aqui para efetuar uma medição, mas, neste caso, isso se trata de algo válido. Uma vantagem clara do arquivo de log é que será possível ver o comportamento de algo que já aconteceu e que não será possível simular em ambiente de desenvolvimento. Por exemplo, um relato de um gerente dizendo ontem às 18h30 a aplicação ficou instável se torna uma pista extremamente útil, caso existam entradas úteis nos arquivos de log para este horário. A lição aqui é simples: utilize arquivos de log para relatar os passos críticos de sua aplicação. Mas sempre tenha cuidado para não colocar entradas desnecessárias ou redundantes. Entradas de log dentro de um método chamado repetidas vezes poluem o log com o mesmo texto e atrapalham ao invés de ajudar. Outra ferramenta utilizada é efetuar debugs na aplicação em busca do mesmo comportamento de erro relatado. Efetuar debug é uma das técnicas para se achar problemas de performance, sem dúvida. Mas fique atento, pois depois de alguns minutos efetuando o debug de uma aplicação, às vezes por acidente passamos da etapa procurada dentro da aplicação. Lembre-se que em debug, o comportamento do paralelismo da aplicação será certamente modificado. Use break points condicionais nos casos em que busca uma determinada condição ao invés de controlar a execução do debug passo a passo olhando o valor de cada variável. O break point condicional somente será ativado caso uma condição seja satisfeita. No eclipse proceda de acordo com o mostrado nas figuras. Outras plataformas de desenvolvimento possuem recursos semelhantes. Mas se lembre que debug nem sempre é uma opção conveniente, principalmente em se tratando de heisenbugs. 21 \

7 Figura 8. Habilitando break point condicional. Profillers Uma das melhores formas de encontrar gargalos na execução de códigos é utilizando um profiller. Nem sempre é possível anexá-lo ao ambiente o qual o problema se manifesta. Quando é possível, seu uso é sem dúvida uma das formas mais efetivas de descobrir o que está causando um determinado comportamento ou problema de performance. Existem diferentes profillers no mercado. A maior parte tem o foco em gravar e/ou visualizar o que está acontecendo durante a execução de um código. Alguns deles têm o custo aparentemente elevado no mercado, mas isto possui um motivo: eles interferem menos na execução da aplicação do que outros. Vale a pena executar uma versão de teste destes profillers para avaliar, ou mesmo para resolver um problema pontual que esteja ocorrendo. O autor deste artigo não possui nenhum vínculo com fornecedores, mas sugere que o leitor teste o Oracle Visual VM, o JProfiller e o Yourkit. Eles são parecidos em suas funções e a preferência por determinado profiller pode se tornar uma preferência tão subjetiva quanto à preferência por algum ambiente de desenvolvimento. Tire suas próprias conclusões. Neste artigo estão sendo usadas imagens de uma execução do Oracle Visual VM, mas tenha em mente que outros profillers possuem funções semelhantes. Figura 9. Profiller exibindo uso de memória e outros gráficos. Algumas das principais visualizações disponíveis são: execução de threads, tempo gasto durante a execução de métodos, monitor mostrando gráficos de memória heap e perm gen space, e memória gasta por quantidade de objetos alocados. A importância da visualização do monitor é mostrar o comportamento do garbage collector e também se existem muitos objetos retidos durante a execução. É possível ver qual o tipo de objeto que está consumindo mais memória durante a execução. Da mesma forma, é possível ver o método que está gastando mais tempo. Esta visualização será uma das mais importantes quando se estiver procurando gargalos durante uma execução. O ponto de maior demora será o candidato à otimização, se possível com paralelismo. Raramente uma aplicação tem como seu maior problema o consumo de CPU. Normalmente os gargalos estão ligados a outros fatores e a demora é uma consequência da forma com que o programa foi desenhado. Nos casos em que CPU é um dos fatores determinantes para problemas de performance, a escolha do profiller deve ser feita depois de se testar algumas possibilidades. Possibilidade de paralelismo: existindo, prepare seu código Utilizando uma das técnicas citadas anteriormente é possível encontrar os pontos onde está sendo gasto mais tempo na aplicação. Sair deste ponto para paralelizar o código nem sempre é simples. Existe a necessidade de analisar alguns aspectos, dentre eles se existe um grande volume de informação que possa ser dividido para ser processado, e se a demora acontece de fato neste ponto. Quando o tempo de processamento cresce com o volume de informação, geralmente é possível paralelizar de alguma forma. Nesta etapa, as métricas citadas anteriormente serão úteis para que a refatoração não seja feita no escuro. Comece verificando se o ponto o qual será feita a alteração está isolado de alguma forma ou não. Por isolado, falando de forma clara: a etapa onde será feito o paralelismo está em uma ou poucas classes fáceis de controlar? Se a resposta para esta pergunta for não, comece por uma refatoração extraindo uma interface que terá sua implementação paralelizada internamente. Assim, será possível mudar entre a versão paralela ou sequencial de forma simples. Temos um cenário hipotético, onde é necessário finalizar os pedidos de uma empresa, listando suas filiais e notas, de acordo com o código da Listagem 2. Listagem 2. Cenário hipotético a ser paralelizado. public void finalizapedidos(long empresaid){ Empresa e = dao.buscaempresa(empresaid); List<Filial> filiais = dao.listarfiliais(e); for(filial f: filiais){ List<Notas> notas = dao.listarnotas(f); for(nota n: notas){ List<Imposto> impostos = / 22

8 gerarimpostos(n); // ponto onde ocorre demora devido ao grande // numero de itens Este código não possui uma interface clara onde é separado o ponto onde ocorre a demora. O fato de utilizar paralelismo não elimina outras possibilidades de otimização, como, por exemplo, deixar o seu mapeamento objeto relacional de lado por um momento e efetuar uma query pesada em SQL nativo JDBC com otimizações como fetch result size coerente (no caso de leitura em massa), ou efetuar batch inserts/update em JDBC (no caso de gravação de massa de dados). Estes assuntos fogem ao escopo do artigo, mas vale a pena dar uma olhada nas referências e fazer alguns testes, pois a falta de uso destes recursos infelizmente é comum. No exemplo o número de acessos ao banco de dados será reduzido com apenas um método da classe DAO sendo chamada ao invés de dois. Listagem 3. Primeira refatoração: simplificando acesso a dados externos. public Status finalizapedidos(long empresaid){ ResultSet rs = dao.listarnotasparatodasasfiliais(empresaid); while(rs.next()){ Nota n = converter(rs); // ponto onde ocorre demora devido ao grande // numero de itens No exemplo acima foi retornado um objeto Result- Set onde cada entrada é convertida em um objeto de domínio por demanda. Este ponto fictício foi feito propositalmente para exemplificar um possível uso de um objeto ResultSet com fetch result size coerente ou mesmo uma SQL nativa otimizada. Listagem 4. Segunda refatoração: preparando para o paralelismo. private FinalizadorPedidoEmLote finalizadoremlote = new FinalizacaoSequencial(); public Status finalizapedidos(long empresaid){ Iterable<Notas> notas = dao.listarnotasparatodasasfiliais(empresaid); List< FinalizacaoPedido > finalizacoes = new LinkedList< FinalizacaoPedido >(); for(nota n: notas){ // cada processamento sera agrupado finalizacoes(new FinalizacaoPedido(n)); // e seu processamento sera feito em um ponto // externo finalizadoremlote.processar(finalizacoes); // Interface onde a finalizacao do lote de pedidos sera // executada public interface FinalizadorPedidoEmLote{ public Status processar(collection< FinalizacaoPedido > finalizacoes); // Implementação padrão seqüencial. Aqui o tempo deve // ser próximo do original, pois tudo acontece ainda de // forma seqüencial public class FinalizacaoSequencial implements FinalizadorPedidoEmLote { public Status processar(collection< FinalizacaoPedido > finalizacoes){ for(finalizacaopedido f: finalizacoes){ f.execute(); // retornar o Status de acordo com o resultado... public class FinalizacaoPedido implements Callable<StatusPedido>{ private final Nota nota; public FinalizacaoPedido(Nota n){ this.nota = n; public Status StatusPedido call() throws Exception { // ponto onde ocorre demora, mas onde sera // executado item a item Repare que o código de exemplo praticamente triplicou de tamanho mesmo com a implementação onde ocorre a demora sendo omitida. Mas, de fato, o código que irá demandar manutenção de negócio será isolado na maior parte do tempo dentro da classe FinalizacaoPedido. Então, apesar do aumento, a manutenção poderá ser simplificada. Analisando o que foi feito, temos que o processamento de cada item é isolado dentro de uma classe FinalizacaoPedido, e sua execução é postergada para o final do método, onde temos outra classe controlando a execução desta coleção de finalizações de pedido. O que foi 23 \

9 feito ainda é uma implementação padrão sequencial. Não foi introduzido nenhum conceito de programação paralela. A interface FinalizadorPedidoEmLote será implementada pelo novo código para processamento em paralelo. É interessante escrever testes unitários para esta interface. Os testes devem funcionar inicialmente com a implementação sequencial, e posteriormente devem funcionar na implementação nova em paralelo. Coloque em seus testes uma medição do tempo gasto na execução do FinalizadorPedidoEmLote, pois assim dados preciosos comparando as execuções em paralelo e sequencial irão mostrar se de fato houve vantagem no paralelismo. Repare que o trabalho maior a ser feito foi preparar o código para paralelismo. Até então não houve codificação com nenhuma classe da API de concorrência do Java, exceto pelo uso da interface Callable. Tenha em mente os preceitos de programação funcional explicados anteriormente. Deixe para efetuar side-effects fora da classe de execução de baixa granularidade (fora da classe FinalizacaoPedido neste exemplo), pois assim o paralelismo será máximo. Caso exista a necessidade de consultas ou alteração do banco de dados dentro desta classe, não havendo outra alternativa, verifique através de testes se existe vantagem real no paralelismo. Reforçando o que já foi dito, normalmente batch insert/updates do JDBC ou otimizações na parametrização dos objetos ResultSet possuem bons resultados. Se existir dúvida, teste ambos os casos e meça o tempo de execução de ambas as possibilidades. Acredite nos resultados medidos e não em suposições. Implementação em paralelo Após feito o trabalho de isolar a execução no item anterior, paralelizar a execução se torna algo trivial. Neste exemplo iremos usar a API de execução do Java 5 através da utilização da classe ExecutorService. Listagem 5. Primeiro exemplo de implementação de código em paralelo. public class FinalizadorEmParalelo implements FinalizadorPedidoEmLote{ public Status processar(collection< FinalizacaoPedido > finalizacoes){ // ThreadPool com 4 threads em paralelo ExecutorService e = Executors. newfixedthreadpool(4); // Aqui acontece a execução em paralelo Collection<Future<StatusPedido>> c = e.invokeall(finalizacoes); // desligue o ThreadPool para evitar desperdício de // recursos e.shutdown(); // retornar o Status de acordo com o resultado... O código em paralelo não ficou complexo, graças à refatoração feita anteriormente. Alguns pontos interessantes devem ser destacados, como, por exemplo, o fato da regra de negócio ter ficado isolada na classe de baixa granularidade FinalizacaoPedido faz com que seja simples trocar entre uma implementação e outra. A classe Future também possui um comportamento interessante. Ao invocar o método get(), caso este item não tenha sido executado ainda, o método get() ficará bloqueado, aguardando o retorno. Então é possível iterar o resultado de todas as chamadas efetuadas da mesma forma que seria feito em um loop no resultado sequencial. O interessante aqui é que o código que está sendo usado para controlar o paralelismo é todo da API de concorrência do Java. Não existe nenhum lock explícito, chamada de métodos como sleep, notify ou yield, ou outra manipulação de resultado produzir itens para PROCESSAMENTO em paralelo executar itens em paralelo usando threadpool (executer) trabalhar com o resultado Figura 10. Primeira abordagem de paralelismo, produzindo os itens para posterior processamento em paralelo. / 24

10 thread explícita. Isso introduz simplicidade no código, deixa a manutenção mais simples e torna o código legível. Mas para fazer código simples é necessário entender o que acontece. Por isso foi dada a explicação anterior sobre dead locks, side effects e afins. Foi feito o exemplo com finalização de pedidos para que fosse possível ver uma aplicação próxima do mundo real. Mas é importante destacar que deve existir um ponto para processamento em baixa granularidade, e um ponto para controlar a execução do processamento como um todo. Este segundo, pode ter uma implementação inicial sequencial, e uma implementação posterior paralela, conforme foi feito neste exemplo. O ponto de baixa granularidade (a implementação da classe Callable) poderá ter um retorno que será utilizado pela execução do processamento como um todo. Diminuindo o consumo de memória Vale lembrar que no exemplo de refatoração mostrado anteriormente, é provável que se esteja trabalhando com um número elevado de itens. Dependendo da quantidade de itens a serem agrupados antes de dividir o processamento, é bem possível que ocorram problemas devido ao uso excessivo de memória, como, por exemplo, um OutOfMemoryError. Outra questão é que, esperar o agrupamento terminar implica em mais um gargalo. Caso a produção destes itens envolva um tempo considerável ou envolva um gasto de memória considerável, vale a pena avaliar a possibilidade de produzir e consumir estes itens ao mesmo tempo, utilizando o pattern Producer/Consumer. Neste padrão existe uma thread produzindo itens para que outra thread consuma-os. É interessante destacar que o consumo de memória é reduzido pelo fato de não precisar produzir todos os itens (às vezes falamos de milhões de objetos) para iniciar o processamento. Desenhe o código para que seja possível utilizar um threadpool com itens produtores e outro thread pool para efetuar o consumo destes itens. Utilize uma coleção da API de concorrência do Java para armazenar os itens que estão sendo produzidos e consumidos. No exemplo anterior, cada item a ser processado foi implementado como uma instância de Callable, o que permite que este item seja chamado por um thread pool Executor da API de concorrência do Java. Esta é uma possibilidade. A outra possibilidade é que a classe executada não represente o item a ser processado, mas simplesmente o produza ou o consuma. O segundo exemplo será implementado desta forma. Vale lembrar que, ao trabalhar com thread pool dos dois lados (produtor e consumidor), caso a produção de itens esteja mais rápida que o consumo ou vice-versa, é possível aumentar o número de threads no thread pool mais lento. É importante testar este comportamento em condições próximas de onde a aplicação será instalada em produção, para se obter dados mais reais. É importante destacar que, no caso de haver paralelismo no produtor, deve-se tomar o cuidado de não produzir itens duplicados. Em caso de leitura no banco de dados, por exemplo, uma das formas é definir um intervalo de dados por produtor. Como sempre, a melhor abordagem é começar de forma simples e sem otimizações prematuras. Se paralelizar o produtor estiver complicado demais, pode-se iniciar com apenas um produtor e depois, se houver necessidade, efetuar a refatoração para o paralelismo do produtor. Listagem 6. Exemplo de produtor-consumidor. public class Produtor implements Callable<Void>{ public Produtor(BloquingQueue<Item> itens){ this.items = itens; private final BloquingQueue<Item> itens; public Void call() throws Exception{ while(/* existem mais itens para produzir */){ Item item = // efetue a produção dos itens itens.offer(item); public class Consumidor implements Callable<Void>{ public Consumidor(BloquingQueue<Item> itens){ this.items = itens; private final BloquingQueue<Item> itens; public Void call() throws Exception{ while(/* existem mais itens para consumir */){ //Recuperar e retirar da coleção itens o proximo //item abaixo. Item item = itens.pool(10,timeunit. SECONDS); consumir(item) Aqui temos as classes produtoras e consumidoras feitas. Existem algumas decisões a serem tomadas aqui. Para o argumento do while do consumidor é possível validar a existência de itens novos a serem processa- 25 \

11 dos ou simplesmente efetuar um loop infinito, para que em momento posterior seja feita a verificação de novos itens. Outras formas de coordenar a execução dos produtores e consumidores podem ser usadas, pois no caso de não haverem mais itens sendo produzidos, os consumidores devem parar a execução. Verifique a documentação das coleções concorrentes, dentre elas a BloquingQueue, para então conhecer e efetuar a escolha da coleção mais coerente de acordo com seu cenário. Veja também a documentação da classe CountDownLatch, que também pode ser utilizada para coordenar execução em alguns cenários. Listagem 7. Código de controle do thread pool para o produtor. O mesmo código para o consumidor é semelhante. BloquingQueue<Item> itens = //... // paralelismo escolhido para produtores (numero de // threads em paralelo) int paralelismoprodutores = //... ExecutorService poolprodutores = Executors.newFixedSizeThreadPool(paralelismo Produtores); Collection<Produtor> produtores = //... for(int i=0;i<paralelismoprodutores;i++){ produtores.add(new Produtor(itens)); poolprodutores.invokeall(produtores); poolprodutores.shutdown(); No código anterior foi criado um thread pool e foram adicionados o mesmo número de Callables para execução. A coleção itens será compartilhada entre todas as threads. Assim é possível manter todas as threads criadas ocupadas. Para a instância da variável itens, certifique-se de usar uma coleção da API de concorrência neste ponto (package java.util.concurrent) ou uma classe thread safe (feita para não haver dead locks ou inconsistência durante a execução em paralelo). A preparação da execução dos consumidores é semelhante ao que foi feito para os produtores e será omitida. Mas um ponto de atenção nos consumidores é quando parar a execução. Uma das formas é efetuar a chamada do método que retira itens da coleção com um timeout. Por exemplo, utilizando o método BlockingQueue#pool(long, TimeUnit) para recuperar um item no consumidor, é possível receber o valor null quando não houverem mais itens disponíveis dentro de um tempo limite especificado. Passado o tempo de tolerância para produção de um novo item, pode-se parar o processamento no consumidor (colocando-se um break em um loop infinito, por exemplo). Outra forma é compartilhar um AtomicBoolean entre os produtores e consumidores. Mais uma vez, os testes são necessários para evitar uma execução infinita. Não se esqueça neste ponto de utilizar um profiller para se certificar que ambos os thread pools estão sendo executados de forma satisfatória. COLEção de itens COMPARTILHADA uma ou mais threads produzem itens a serem processados ao mesmo tempo uma ou mais threads consomem os itens produzidos x Figura 11. Segunda abordagem para processamento em paralelo, onde a produção e o consumo de itens ocorre ao mesmo tempo em diferentes threads ou thread pools. / 26

12 Alguns cuidados que devem ser tomados Durante testes com paralelismo, ao obter resultados extremamente satisfatórios, é possível que ocorra uma ansiedade por dar notícias de melhoria ou mesmo por colocar código novo em produção. Certifique-se de testar em cenário realista, o mais próximo possível do cenário em produção. Durante qualquer refatoração de código é possível se esquecer de alguma etapa importante, e com isso ver um cenário mais otimista do que o cenário real. Geralmente notícias de melhoria de performance espalham-se sozinhas. Apenas espalhe notícias de melhoria após validar em produção, ou tenha muitas evidências de testes. Certifique-se também de que voltar o código sequencial seja possível e simples. Voltar código anterior deve ser simples em qualquer cenário de reinstalação, mas no caso da troca de código sequencial por paralelo, isto se torna absurdamente importante. O código feito neste momento foi feito com os cuidados necessários para se evitar side effects indesejados, dead locks e inconsistências. Mas nada garante que componentes alheios estejam preparados para execução em paralelo. O autor deste artigo já se deparou algumas vezes com este cenário. A volta do código sequencial não foi necessária, mas tratamento de erros adicional durante a interação com componentes alheios teve que ser feito. Lembrando ainda dos heisenbugs: alguns erros de processamento paralelo somente poderão acontecer em produção. O desenvolvedor tem que estar preparado. Conclusões Paralelismo é uma ótima forma de atingir melhoria de performance em casos de processamento de grande volume de dados. Por outro lado, é simples desenvolver código paralelo sem desempenho satisfatório, ou pior ainda, código paralelo que gere resultados inconsistentes. A plataforma Java possui muitas boas abstrações e ferramentas para efetuar desenvolvimento de código paralelo simples e de fácil manutenção, sem, para isso, deixar de lado o desempenho. Sejam as coleções da API de concorrência, o ExecutorService ou outras abstrações, é possível obter paralelismo satisfatório utilizando em conjunto conceitos de programação funcional, como, por exemplo, funções puras durante o paralelismo para evitar locking. Utilizar orientação a objetos de forma que seja possível trocar o código sequencial por paralelo aliado a outras técnicas como TDD ou mesmo o uso de profillers ajuda a mensurar se houve melhorias de performance com o código novo. Assim, a troca de código pode ser feita sem maiores preocupações por parte do desenvolvedor. Caso o leitor tenha gostado da abordagem funcional, vale a pena se aprofundar no assunto, seja estudando linguagens que utilizem este paradigma, como, por exemplo, Erlang, ou dentro da JVM, Clojure ou Scala. O modelo de concorrência utilizando atores é particularmente interessante. Resolver problemas envolvendo perfomance, paralelismo ou grande quantidade de dados pode ser algo que tire o sono do desenvolvedor. Mas ao seguir alguns preceitos a resolução deste tipo de problema torna-se divertida e recompensadora para o desenvolvedor. > > problem > > concurrency-vs-parallelism-what-is-the-difference > > science) > > > Bloch/dp/ > Brian-Goetz/dp/ > > > > visualvm/index.html > > getstart/resultset.html > > > > > /referências 27 \

Dois clientes com a mesma data de pagamento não podem compartilhar instâncias

Dois clientes com a mesma data de pagamento não podem compartilhar instâncias Capítulo 3. Tópicos de Orientação a Objetos correr o risco de cair na armadilha da quebra de encapsulamento e alto acoplamento. Repare que, desta forma, o acoplamento é bem menor, nenhuma das classes precisa

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

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

INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA DE ALAGOAS CURSO TECNICO EM INFORMATICA DISCIPLINA:

INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA DE ALAGOAS CURSO TECNICO EM INFORMATICA DISCIPLINA: INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA DE ALAGOAS CURSO TECNICO EM INFORMATICA DISCIPLINA: PROGRAMAÇÃO ORIENTADA A OBJETOS PROFESSOR: REINALDO GOMES ASSUNTO: REVISÃO DA INTRODUÇÃO A ORIENTAÇÃO

Leia mais

Computação Concorrente (MAB-117) Monitores

Computação Concorrente (MAB-117) Monitores Computação Concorrente (MAB-117) Monitores Prof. Silvana Rossetto 1 Departamento de Ciência da Computação (DCC) Instituto de Matemática (IM) Universidade Federal do Rio de Janeiro (UFRJ) Maio de 2012 1.

Leia mais

EMENTA DO CURSO. Tópicos:

EMENTA DO CURSO. Tópicos: EMENTA DO CURSO O Curso Preparatório para a Certificação Oracle Certified Professional, Java SE 6 Programmer (Java Básico) será dividido em 2 módulos e deverá ter os seguintes objetivos e conter os seguintes

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

Sistemas Operacionais Aula 06: Threads. Ezequiel R. Zorzal ezorzal@unifesp.br www.ezequielzorzal.com

Sistemas Operacionais Aula 06: Threads. Ezequiel R. Zorzal ezorzal@unifesp.br www.ezequielzorzal.com Sistemas Operacionais Aula 06: Threads Ezequiel R. Zorzal ezorzal@unifesp.br www.ezequielzorzal.com Objetivos Introduzir o conceito de thread Discutir as APIs das bibliotecas de threads Pthreads, Win32

Leia mais

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

Sistemas Distribuídos

Sistemas Distribuídos Sistemas Distribuídos Processos e Threads Gustavo Reis gustavo.reis@ifsudestemg.edu.br - O que são Processos? Uma abstração de um programa em execução. Mantêm a capacidade de operações (pseudo)concorrentes,

Leia mais

SCALA + AKKA. programação multithread de maneira fácil Introdução ao

SCALA + AKKA. programação multithread de maneira fácil Introdução ao scala akka_ SCALA + AKKA programação multithread de maneira fácil Introdução ao Hoje em dia, visto que processadores ganham cada vez mais núcleos, é de extrema importância que, além de criar sistemas multithread

Leia mais

(ou seja, boas praticas de programação orientada a objetos devem ser empregadas mesmo se não foram explicitamente solicitadas)

(ou seja, boas praticas de programação orientada a objetos devem ser empregadas mesmo se não foram explicitamente solicitadas) PC-2 / LP-2 2009/2 Lista 2 Prof. Alexandre Sztajnberg Em todos os exercícios a(o) aluna(o) deve, além de atender aos requisitos enunciados, utilizar os conceitos e características de orientação a objetos

Leia mais

Fundamentos de Programaçã. ção Concorrente

Fundamentos de Programaçã. ção Concorrente Java 2 Standard Edition Fundamentos de Programaçã ção Concorrente Helder da Rocha www.argonavis.com.br 1 Programação concorrente O objetivo deste módulo é oferecer uma introdução a Threads que permita

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

FBV - Linguagem de Programação II. Um pouco sobre Java

FBV - Linguagem de Programação II. Um pouco sobre Java FBV - Linguagem de Programação II Um pouco sobre Java História 1992: um grupo de engenheiros da Sun Microsystems desenvolve uma linguagem para pequenos dispositivos, batizada de Oak Desenvolvida com base

Leia mais

FAT32 ou NTFS, qual o melhor?

FAT32 ou NTFS, qual o melhor? FAT32 ou NTFS, qual o melhor? Entenda quais as principais diferenças entre eles e qual a melhor escolha O que é um sistema de arquivos? O conceito mais importante sobre este assunto, sem sombra de dúvidas,

Leia mais

[MANUAL DE INTEGRAÇÃO PARA SITES DE MEMBROS]

[MANUAL DE INTEGRAÇÃO PARA SITES DE MEMBROS] 2011 [MANUAL DE INTEGRAÇÃO PARA SITES DE MEMBROS] Destinado a usuários que desejam vender conteúdo premium, disponível em sites de membros, através da plataforma Hotmart. Versão do documento: 1.0, 11/04/2011.

Leia mais

MANUAL DO SAHEC. Sistema de Agendamento de Horários para Elaboração de Cálculos

MANUAL DO SAHEC. Sistema de Agendamento de Horários para Elaboração de Cálculos MANUAL DO SAHEC Sistema de Agendamento de Horários para Elaboração de Cálculos VERSÃO 1.0 Outubro/2013 Manual do SAHEC Sindicato dos Médicos de São Paulo www.simesp.org.br Conteúdo 1. COMPATIBILIDADE COM

Leia mais

Modelagem e Implementação (Incremental de um Software para Controle) de Aquário de Peixes

Modelagem e Implementação (Incremental de um Software para Controle) de Aquário de Peixes Modelagem e Implementação de Aquário de Peixes- por Jorge Fernandes - Página 1 Modelagem e Implementação (Incremental de um Software para Controle) de Aquário de Peixes Jorge Fernandes Natal, Agosto de

Leia mais

Teste de software. Definição

Teste de software. Definição Definição O teste é destinado a mostrar que um programa faz o que é proposto a fazer e para descobrir os defeitos do programa antes do uso. Quando se testa o software, o programa é executado usando dados

Leia mais

Desenvolvendo Aplicações Web com NetBeans

Desenvolvendo Aplicações Web com NetBeans Desenvolvendo Aplicações Web com NetBeans Aula 3 Cap. 4 Trabalhando com Banco de Dados Prof.: Marcelo Ferreira Ortega Introdução O trabalho com banco de dados utilizando o NetBeans se desenvolveu ao longo

Leia mais

Evolução do Design através de Testes e o TDD

Evolução do Design através de Testes e o TDD c a p a Lucas Souza (lucas.souza@caelum.com.br): é bacharel em Engenharia da Computação pela Universidade de Ribeirão Preto, possui a certificação SCJP e trabalha com Java há 4 anos. Atualmente é desenvolvedor

Leia mais

Tópicos de Orientação a Objetos

Tópicos de Orientação a Objetos Capítulo 3 Tópicos de Orientação a Objetos Um bom design de software visa a uma arquitetura flexível que permita futuras alterações, facilite a produção de código organizado e legível, maximizando seu

Leia mais

O CONCEITO DE TDD NO DESENVOLVIMENTO DE SOFTWARE

O CONCEITO DE TDD NO DESENVOLVIMENTO DE SOFTWARE O CONCEITO DE TDD NO DESENVOLVIMENTO DE SOFTWARE Renan Leme Nazário, Ricardo Rufino Universidade Paranaense (Unipar) Paranavaí PR - Brasil renazariorln@gmail.com, ricardo@unipar.br Resumo. Este artigo

Leia mais

Comparativo de desempenho do Pervasive PSQL v11

Comparativo de desempenho do Pervasive PSQL v11 Comparativo de desempenho do Pervasive PSQL v11 Um artigo Pervasive PSQL Setembro de 2010 Conteúdo Resumo executivo... 3 O impacto das novas arquiteturas de hardware nos aplicativos... 3 O projeto do Pervasive

Leia mais

Um sistema é constituído de um conjunto de processos que executam seus respectivos códigos do sistema operacional e processos e códigos de usuários.

Um sistema é constituído de um conjunto de processos que executam seus respectivos códigos do sistema operacional e processos e códigos de usuários. Os sistemas computacionais atuais permitem que diversos programas sejam carregados na memória e executados simultaneamente. Essa evolução tornou necessário um controle maior na divisão de tarefas entre

Leia mais

Boas Práticas de Desenvolvimento Seguro

Boas Práticas de Desenvolvimento Seguro Boas Práticas de Desenvolvimento Seguro Julho / 2.012 Histórico de Revisões Data Versão Descrição Autor 29/07/2012 1.0 Versão inicial Ricardo Kiyoshi Página 2 de 11 Conteúdo 1. SEGURANÇA DA INFORMAÇÃO

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

Identificação rápida de gargalos Uma forma mais eficiente de realizar testes de carga. Um artigo técnico da Oracle Junho de 2009

Identificação rápida de gargalos Uma forma mais eficiente de realizar testes de carga. Um artigo técnico da Oracle Junho de 2009 Identificação rápida de gargalos Uma forma mais eficiente de realizar testes de carga Um artigo técnico da Oracle Junho de 2009 Identificação rápida de gargalos Uma forma mais eficiente de realizar testes

Leia mais

as cinco principais batalhas do monitoramento e como você pode vencê-las

as cinco principais batalhas do monitoramento e como você pode vencê-las DOCUMENTAÇÃO TÉCNICA Setembro de 2012 as cinco principais batalhas do monitoramento e como você pode vencê-las agility made possible sumário resumo executivo 3 efetivo do servidor: 3 difícil e piorando

Leia mais

Descobrindo o Profiling de

Descobrindo o Profiling de artigo Descobrindo o Profiling de Aplicações Java com JProfiler Aprenda como encontrar problemas de performance na sua aplicação com o JProfiler. Muitas vezes, nos deparamos com problemas de performance

Leia mais

Módulo 06 Desenho de Classes

Módulo 06 Desenho de Classes Módulo 06 Desenho de Classes Última Atualização: 13/06/2010 1 Objetivos Definir os conceitos de herança, polimorfismo, sobrecarga (overloading), sobreescrita(overriding) e invocação virtual de métodos.

Leia mais

2 Modelos de Implementação

2 Modelos de Implementação 2 Modelos de Implementação Os modelos de concorrência definem como uma aplicação atende às requisições concorrentes. Os modelos de sandboxes definem como o ambiente das aplicações são criados. Os modelos

Leia mais

BANCO DE DADOS. Introdução a Banco de Dados. Conceitos BásicosB. Engenharia da Computação UNIVASF. Aula 1. Breve Histórico

BANCO DE DADOS. Introdução a Banco de Dados. Conceitos BásicosB. Engenharia da Computação UNIVASF. Aula 1. Breve Histórico Banco de Dados // 1 Banco de Dados // 2 Conceitos BásicosB Engenharia da Computação UNIVASF BANCO DE DADOS Aula 1 Introdução a Banco de Dados Campo representação informatizada de um dado real / menor unidade

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 (carlos@tosin.com.br) é formado em Ciência da Computação pela PUC-PR, pós-graduado

Leia mais

Introdução a Threads Java

Introdução a Threads Java Introdução a Threads Java Prof. Gerson Geraldo Homrich Cavalheiro Universidade Federal de Pelotas Departamento de Informática Instituto de Física e Matemática Pelotas RS Brasil http://gersonc.anahy.org

Leia mais

Introdução ao OpenUP (Open Unified Process)

Introdução ao OpenUP (Open Unified Process) Introdução ao OpenUP (Open Unified Process) Diferentes projetos têm diferentes necessidades de processos. Fatores típicos ditam as necessidades de um processo mais formal ou ágil, como o tamanho da equipe

Leia mais

Processos (Threads,Virtualização e Migração de Código)

Processos (Threads,Virtualização e Migração de Código) Processos (Threads,Virtualização e Migração de Código) Roteiro Processos Threads Virtualização Migração de Código O que é um processo?! Processos são programas em execução. Processo Processo Processo tem

Leia mais

Notas da Aula 6 - Fundamentos de Sistemas Operacionais

Notas da Aula 6 - Fundamentos de Sistemas Operacionais 1. Monitores Notas da Aula 6 - Fundamentos de Sistemas Operacionais Embora os semáforos sejam uma boa solução para o problema da exclusão mútua, sua utilização não é trivial. O programador é obrigado a

Leia mais

Banco de Dados Aula 1 Introdução a Banco de Dados Introdução Sistema Gerenciador de Banco de Dados

Banco de Dados Aula 1 Introdução a Banco de Dados Introdução Sistema Gerenciador de Banco de Dados Banco de Dados Aula 1 Introdução a Banco de Dados Introdução Um Sistema Gerenciador de Banco de Dados (SGBD) é constituído por um conjunto de dados associados a um conjunto de programas para acesso a esses

Leia mais

Prof. Marcelo Heitor Teixeira marceloheitor.com. Java Exceções e Finalizações

Prof. Marcelo Heitor Teixeira marceloheitor.com. Java Exceções e Finalizações Prof. Marcelo Heitor Teixeira marceloheitor.com Java Exceções e Finalizações # Exceções em Java # Hierarquia de Classes # Lançando, Declarando e Capturando # Classes de Exceções Personalizadas # Entendendo

Leia mais

Performance JEE. Haroldo R. J. de Macêdo hmacedo@br.ibm.com

Performance JEE. Haroldo R. J. de Macêdo hmacedo@br.ibm.com Performance JEE Haroldo R. J. de Macêdo hmacedo@br.ibm.com Agenda Conceitos de performance Testes para performance Lições aprendidas 15/09/2009 Performance JEE - Just Java 2009 2 Programa Java x JEE Java

Leia mais

Capítulo 2 Processos e Threads Prof. Fernando Freitas

Capítulo 2 Processos e Threads Prof. Fernando Freitas slide 1 Capítulo 2 Processos e Threads Prof. Fernando Freitas Material adaptado de: TANENBAUM, Andrew S. Sistemas Operacionais Modernos. 3ª edição. Disponível em: http://www.prenhall.com/tanenbaum_br slide

Leia mais

Classes de Entidades Persistentes JDB

Classes de Entidades Persistentes JDB Classes de Entidades Persistentes JDB Brasil, Natal-RN, 07 de setembro de 2011 Welbson Siqueira Costa www.jdbframework.com Nota de Retificação: em 11/12/2011 a Listagem 3 desse tutorial sofreu uma pequena

Leia mais

UTILIZANDO ICONIX NO DESENVOLVIMENTO DE APLICAÇÕES DELPHI

UTILIZANDO ICONIX NO DESENVOLVIMENTO DE APLICAÇÕES DELPHI UTILIZANDO ICONIX NO DESENVOLVIMENTO DE APLICAÇÕES DELPHI Dr. George SILVA; Dr. Gilbert SILVA; Gabriel GUIMARÃES; Rodrigo MEDEIROS; Tiago ROSSINI; Centro Federal de Educação Tecnológica do Rio Grande do

Leia mais

LEVANTAMENTO DE REQUISITOS SEGUNDO O MÉTODO VOLERE

LEVANTAMENTO DE REQUISITOS SEGUNDO O MÉTODO VOLERE LEVANTAMENTO DE REQUISITOS SEGUNDO O MÉTODO VOLERE RESUMO Fazer um bom levantamento e especificação de requisitos é algo primordial para quem trabalha com desenvolvimento de sistemas. Esse levantamento

Leia mais

Dado: Fatos conhecidos que podem ser registrados e têm um significado implícito. Banco de Dados:

Dado: Fatos conhecidos que podem ser registrados e têm um significado implícito. Banco de Dados: MC536 Introdução Sumário Conceitos preliminares Funcionalidades Características principais Usuários Vantagens do uso de BDs Tendências mais recentes em SGBDs Algumas desvantagens Modelos de dados Classificação

Leia mais

Capítulo 1. Introdução. 1.1 Linguagens. OBJETIVOS DO CAPÍTULO Ao final deste capítulo você deverá ser capaz de:

Capítulo 1. Introdução. 1.1 Linguagens. OBJETIVOS DO CAPÍTULO Ao final deste capítulo você deverá ser capaz de: i Sumário 1 Introdução 1 1.1 Linguagens....................................... 1 1.2 O que é um Compilador?................................ 2 1.3 Processadores de Programas: Compiladores, Interpretadores

Leia mais

Desenvolvendo e Integrando Serviços Multiplataforma de TV Digital Interativa

Desenvolvendo e Integrando Serviços Multiplataforma de TV Digital Interativa Desenvolvendo e Integrando Serviços Multiplataforma de TV Digital Interativa Agenda Introdução Aplicações interativas de TV Digital Desafios de layout e usabilidade Laboratório de usabilidade Desafios

Leia mais

Roteiro. Sistemas Distribuídos. Sistemas de Arquivos Distribuídos. Sistema de arquivos distribuídos

Roteiro. Sistemas Distribuídos. Sistemas de Arquivos Distribuídos. Sistema de arquivos distribuídos Sistemas Distribuídos Sistemas de Arquivos Distribuídos Roteiro Sistema de arquivos distribuídos Requisitos Arquivos e diretórios Compartilhamento Cache Replicação Estudo de caso: NFS e AFS Sistemas Distribuídos

Leia mais

Programação de Computadores - I. Profª Beatriz Profº Israel

Programação de Computadores - I. Profª Beatriz Profº Israel Programação de Computadores - I Profª Beatriz Profº Israel As 52 Palavras Reservadas O que são palavras reservadas São palavras que já existem na linguagem Java, e tem sua função já definida. NÃO podem

Leia mais

Tópicos de Ambiente Web. Modulo 2 Processo de desenvolvimento de um site Professora: Sheila Cáceres

Tópicos de Ambiente Web. Modulo 2 Processo de desenvolvimento de um site Professora: Sheila Cáceres Tópicos de Ambiente Web Modulo 2 Processo de desenvolvimento de um site Professora: Sheila Cáceres Roteiro Motivação Desenvolvimento de um site Etapas no desenvolvimento de software (software:site) Analise

Leia mais

5 Planejamento dos experimentos

5 Planejamento dos experimentos 5 Planejamento dos experimentos Depois de escolher e implementar 5 modelos de concorrência e 4 modelos de sandboxes que consideramos representativos para um servidor web Lua, procuramos os principais fatores

Leia mais

Automatização de Aplicativos Windows usando o AutoHotKey

Automatização de Aplicativos Windows usando o AutoHotKey Automatização de Aplicativos Windows usando o AutoHotKey Muitos processos de negócio dependem de aplicativos de terceiros que assumem a presença de um operador humano para executar determinadas rotinas.

Leia mais

14/09/2008. Curso Superior de Tecnologia em Bando de Dados Disciplina: Projeto de Banco de Dados Relacional II Prof.: Fernando Hadad Zaidan

14/09/2008. Curso Superior de Tecnologia em Bando de Dados Disciplina: Projeto de Banco de Dados Relacional II Prof.: Fernando Hadad Zaidan Faculdade INED Curso Superior de Tecnologia em Bando de Dados Disciplina: Projeto de Banco de Dados Relacional II Prof.: Fernando Hadad Zaidan Unidade 2.2 1 2 Material usado na montagem dos Slides Bibliografia

Leia mais

Banco de Dados I Introdução

Banco de Dados I Introdução Banco de Dados I Introdução Prof. Moser Fagundes Curso Técnico em Informática (Modalidade Integrada) IFSul Campus Charqueadas Sumário da aula Avaliações Visão geral da disciplina Introdução Histórico Porque

Leia mais

Teste e Depuração de Sistemas Web. Prof. Fellipe Aleixo (fellipe.aleixo@ifrn.edu.br)

Teste e Depuração de Sistemas Web. Prof. Fellipe Aleixo (fellipe.aleixo@ifrn.edu.br) Teste e Depuração de Sistemas Web Prof. Fellipe Aleixo (fellipe.aleixo@ifrn.edu.br) Testando Aplicações Web Ê É bem mais complicado testar interfaces Web do que classes de objetos Ê Aplicações WEB não

Leia mais

Garantia de Processo Leis de Lehman Manutenção de Softwares

Garantia de Processo Leis de Lehman Manutenção de Softwares Garantia de Processo Leis de Lehman Manutenção de Softwares Garantia de Processo Acidentes são eventos raros em sistemas críticos e pode ser impossível simulá-los durante testes de um sistema. Requisitos

Leia mais

Prevayler. Perola. André Luís Sales de Moraes Juliana Keiko Yamaguchi Tatiana Yuka Takaki

Prevayler. Perola. André Luís Sales de Moraes Juliana Keiko Yamaguchi Tatiana Yuka Takaki Prevayler Perola André Luís Sales de Moraes Juliana Keiko Yamaguchi Tatiana Yuka Takaki Prevayler Prevayler é a implementação em Java do conceito de Prevalência. É um framework que prega uma JVM invulnerável

Leia mais

No artigo anterior explicamos. Desenvolvimento de Software Dirigido por Caso de Uso. Parte II: Especificando Caso de Uso

No artigo anterior explicamos. Desenvolvimento de Software Dirigido por Caso de Uso. Parte II: Especificando Caso de Uso Desenvolvimento de Software Dirigido por Caso de Uso Parte II: Especificando Caso de Uso Vinicius Lourenço de Sousa viniciuslsousa@gmail.com Atua no ramo de desenvolvimento de software há mais de 10 anos,

Leia mais

Introdução ao uso de Threads em Java

Introdução ao uso de Threads em Java Introdução ao uso de Threads em Java Daniel de Angelis Cordeiro danielc@ime.usp.br 26 de março de 2004 Sumário 1 Introdução 1 1.1 O que são threads?............................... 1 1.2 Todo programa em

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

CÓDIGO DA VAGA: TP05 QUESTÕES DE MÚLTIPLAS ESCOLHAS

CÓDIGO DA VAGA: TP05 QUESTÕES DE MÚLTIPLAS ESCOLHAS QUESTÕES DE MÚLTIPLAS ESCOLHAS 1. Sistemas de gerenciamento de rede tem sua arquitetura baseada em três componentes principais. São eles: a) Protocolo de gerenciamento, protocolo de monitoramento, segurança.

Leia mais

Introdução à Simulação

Introdução à Simulação Introdução à Simulação O que é simulação? Wikipedia: Simulação é a imitação de alguma coisa real ou processo. O ato de simular algo geralmente consiste em representar certas características e/ou comportamentos

Leia mais

Threads em Java. Sistemas Operacionais - Laboratório Professor Machado

Threads em Java. Sistemas Operacionais - Laboratório Professor Machado Threads em Java Sistemas Operacionais - Laboratório Professor Machado 1 Conceitos de Programação Concorrente Uma unidade concorrente é um componente de um programa que não exige a execução seqüencial,

Leia mais

DOMAIN-DRIVEN DESIGN E TEST-DRIVEN DEVELOPMENT

DOMAIN-DRIVEN DESIGN E TEST-DRIVEN DEVELOPMENT DOMAIN-DRIVEN DESIGN E TEST-DRIVEN DEVELOPMENT Jaqueline Rissá Franco email: jaquerifr@gmail.com Karla Marturelli Mattos Luciano Mathias Doll João Almeida Resumo: Este artigo mostra novas abordagens na

Leia mais

Características do Software

Características do Software Questionamentos Por que tanta demora para entregar? Por que os prazos se atrasam? Por que os custos são altos? Por que não achar todos os erros antes de entregar? Por que dificuldade em medir o progresso

Leia mais

JAVA VIRTUAL MACHINE (JVM)

JAVA VIRTUAL MACHINE (JVM) JAVA VIRTUAL MACHINE (JVM) Por Leandro Baptista, Marlon Palangani e Tiago Deoldoto, 11 de Abril de 2009 A linguagem de programação Java proporciona o desenvolvimento aplicações que podem ser executadas

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

Engenharia de Software

Engenharia de Software CENTRO UNIVERSITÁRIO NOVE DE JULHO Profº. Edson T. França edson.franca@uninove.br Software Sistemas Conjunto de elementos, entre os quais haja alguma relação Disposição das partes ou dos elementos de um

Leia mais

2 Auto-sintonia de Bancos de Dados e Agentes de Software

2 Auto-sintonia de Bancos de Dados e Agentes de Software 2 Auto-sintonia de Bancos de Dados e Agentes de Software A uso da abordagem de agentes de software 1 pode trazer benefícios a áreas de aplicação em que é necessário construir sistemas autônomos, ou seja,

Leia mais

Sistemas Operacionais

Sistemas Operacionais Sistemas Operacionais SINCRONIZAÇÃO E COMUNICAÇÃO ENTRE PROCESSOS MACHADO/MAIA: CAPÍTULO 07, PÁGINA 101 Prof. Pedro Luís Antonelli Anhanguera Educacional sistemas multiprogramáveis Os sistemas multiprogramáveis

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

Revisão Ultima aula [1/2]

Revisão Ultima aula [1/2] SOP - TADS Comunicação Interprocessos - 2 IPC Prof. Ricardo José Pfitscher dcc2rjp@joinville.udesc.br Material cedido por: Prof. Rafael Rodrigues Obelheiro Prof. Maurício Aronne Pillon Revisão Ultima aula

Leia mais

Qualidade de Software

Qualidade de Software Qualidade de Software O software é algo abstrato, pois são as instruções que quando executadas atingem o propósito desejado no sistema computacional. (Algoritmo). As principais características são: Complexidade:

Leia mais

Manual do Software: UFV BEER GAME. [Jogue sem moderação] Versão 1.4

Manual do Software: UFV BEER GAME. [Jogue sem moderação] Versão 1.4 Manual do Software: UFV BEER GAME [Jogue sem moderação] Versão 1.4 Como ler esse manual: Esse manual está dividido em duas partes. Na primeira parte é apresentada uma descrição do Beer Game (Jogo da Cerveja)

Leia mais

Nos artigos anteriores apresentamos. Desenvolvimento de Software Dirigido por Caso de Uso Parte III: Caso de Uso de Negócio

Nos artigos anteriores apresentamos. Desenvolvimento de Software Dirigido por Caso de Uso Parte III: Caso de Uso de Negócio Desenvolvimento de Software Dirigido por Caso de Uso Parte III: Caso de Uso de Negócio Vinicius Lourenço de Sousa vinicius.lourenco.sousa@gmail.com Atua no ramo de desenvolvimento de software há mais de

Leia mais

S.O.: Conceitos Básicos

S.O.: Conceitos Básicos S.O.: Conceitos Básicos Camada de software localizada entre o hardware e os programas que executam tarefas para o usuário; Acessa os periféricos Entrada e Saída Esconde os detalhes do hardware para o programador

Leia mais

04/08/2012 MODELAGEM DE DADOS. PROF. RAFAEL DIAS RIBEIRO, M.Sc. @ribeirord MODELAGEM DE DADOS. Aula 2. Prof. Rafael Dias Ribeiro. M.Sc.

04/08/2012 MODELAGEM DE DADOS. PROF. RAFAEL DIAS RIBEIRO, M.Sc. @ribeirord MODELAGEM DE DADOS. Aula 2. Prof. Rafael Dias Ribeiro. M.Sc. MODELAGEM DE DADOS PROF. RAFAEL DIAS RIBEIRO, M.Sc. @ribeirord MODELAGEM DE DADOS Aula 2 Prof. Rafael Dias Ribeiro. M.Sc. @ribeirord 1 Objetivos: Revisão sobre Banco de Dados e SGBDs Aprender as principais

Leia mais

GBC043 Sistemas de Banco de Dados. Introdução. Ilmério Reis da Silva ilmerio@facom.ufu.br www.facom.ufu.br/~ilmerio/sbd UFU/FACOM

GBC043 Sistemas de Banco de Dados. Introdução. Ilmério Reis da Silva ilmerio@facom.ufu.br www.facom.ufu.br/~ilmerio/sbd UFU/FACOM GBC043 Sistemas de Banco de Dados Introdução Ilmério Reis da Silva ilmerio@facom.ufu.br www.facom.ufu.br/~ilmerio/sbd UFU/FACOM Página 2 Definição BD Def. Banco de Dados é uma coleção de itens de dados

Leia mais

Algumas propriedades dos objetos:

Algumas propriedades dos objetos: Orientação a Objetos Vivemos num mundo de objetos. Esses objetos existem na natureza, nas entidades feitas pelo homem, nos negócios e nos produtos que usamos. Eles podem ser categorizados, descritos, organizados,

Leia mais

SISTEMA DE BANCO DE DADOS. Banco e Modelagem de dados

SISTEMA DE BANCO DE DADOS. Banco e Modelagem de dados SISTEMA DE BANCO DE DADOS Banco e Modelagem de dados Sumário Conceitos/Autores chave... 3 1. Introdução... 4 2. Arquiteturas de um Sistema Gerenciador... 5 3. Componentes de um Sistema... 8 4. Vantagens

Leia mais

Entrega e Distribuição

Entrega e Distribuição Entrega e Distribuição 1 - Simplifique o processo de picking e embalagem O nome do jogo é evitar a duplicação de esforços. Os encargos salariais são baseados no tempo, por isso desenhe um gráfico operacional

Leia mais

Banco de Dados I. Introdução. Fabricio Breve

Banco de Dados I. Introdução. Fabricio Breve Banco de Dados I Introdução Fabricio Breve Introdução SGBD (Sistema Gerenciador de Banco de Dados): coleção de dados interrelacionados e um conjunto de programas para acessar esses dados Coleção de dados

Leia mais

Orientação a Objetos

Orientação a Objetos Orientação a Objetos 1. Sobrecarga (Overloading) Os clientes dos bancos costumam consultar periodicamente informações relativas às suas contas. Geralmente, essas informações são obtidas através de extratos.

Leia mais

JDBC. Siga as instruções para instalar o banco de dados H2 e criar a tabela Alunos.

JDBC. Siga as instruções para instalar o banco de dados H2 e criar a tabela Alunos. JDBC CRIANDO O BANCO DE DADOS: Siga as instruções para instalar o banco de dados H2 e criar a tabela Alunos. CRIANDO O PROJETO JAVA PARA DESKTOP: Crie um projeto Java chamado Prograd Crie um pacote chamado

Leia mais

Processamento. Paralelo. e a nova API Fork/Join

Processamento. Paralelo. e a nova API Fork/Join 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

Leia mais

Geração e execução de scripts de teste em aplicações web a partir de casos de uso direcionados por comportamento 64

Geração e execução de scripts de teste em aplicações web a partir de casos de uso direcionados por comportamento 64 direcionados por comportamento 64 5 Estudo de caso Neste capítulo serão apresentadas as aplicações web utilizadas na aplicação da abordagem proposta, bem como a tecnologia em que foram desenvolvidas, o

Leia mais

Sistemas Operativos. Threads. 3º ano - ESI e IGE (2011/2012) Engenheiro Anilton Silva Fernandes (afernandes@unipiaget.cv)

Sistemas Operativos. Threads. 3º ano - ESI e IGE (2011/2012) Engenheiro Anilton Silva Fernandes (afernandes@unipiaget.cv) Sistemas Operativos Threads 3º ano - ESI e IGE (2011/2012) Engenheiro Anilton Silva Fernandes (afernandes@unipiaget.cv) Dos Processos para os Threads O conceito de thread foi introduzido na tentativa de

Leia mais

UFG - Instituto de Informática

UFG - Instituto de Informática UFG - Instituto de Informática Especialização em Desenvolvimento de Aplicações Web com Interfaces Ricas EJB 3.0 Prof.: Fabrízzio A A M N Soares professor.fabrizzio@gmail.com Aula 10 Persistência de Dados

Leia mais

Como Montar um Plano de Estudos Eficiente Para Concurso Público E-book gratuito do site www.concursosemsegredos.com

Como Montar um Plano de Estudos Eficiente Para Concurso Público E-book gratuito do site www.concursosemsegredos.com 1 Distribuição Gratuita. Este e-book em hipótese alguma deve ser comercializado ou ter seu conteúdo modificado. Nenhuma parte deste e-book pode ser reproduzida ou transmitida sem o consentimento prévio

Leia mais

Apresentação. Rio de Janeiro, 19 de fevereiro de 2002 Waldemar Celes

Apresentação. Rio de Janeiro, 19 de fevereiro de 2002 Waldemar Celes Apresentação A disciplina de Estruturas de Dados (ED) está sendo ministrada em sua nova versão desde o segundo semestre de 1998. Trata-se da segunda disciplina de informática oferecida no curso de Engenharia

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

Sistemas Distribuídos

Sistemas Distribuídos Sistemas Distribuídos Modelo Cliente-Servidor: Introdução aos tipos de servidores e clientes Prof. MSc. Hugo Souza Iniciando o módulo 03 da primeira unidade, iremos abordar sobre o Modelo Cliente-Servidor

Leia mais

Engenharia de Requisitos

Engenharia de Requisitos Engenharia de Requisitos Introdução a Engenharia de Requisitos Professor: Ricardo Argenton Ramos Aula 08 Slide 1 Objetivos Introduzir a noção de requisitos do sistema e o processo da engenharia de requisitos.

Leia mais

Turbinando suas aplicações com Multithreading

Turbinando suas aplicações com Multithreading c o l u n a Turbinando suas aplicações com Multithreading do básico ao avançado Turbinando suas aplicações com Multithreading do básico ao avançado Professor J Aplicações, normalmente, executam diversas

Leia mais

Lab de Programação de sistemas I

Lab de Programação de sistemas I Lab de Programação de sistemas I Apresentação Prof Daves Martins Msc Computação de Alto Desempenho Email: daves.martins@ifsudestemg.edu.br Agenda Orientação a Objetos Conceitos e Práticas Programação OO

Leia mais