Desempenho em aplicações Java - Revista Java Magazine 102

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (1)  (0)

Neste artigo serão exibidos casos comuns onde aplicações poderiam ter um desempenho melhor, procurando sempre mostrar ao leitor dicas para serem aplicadas no dia a dia.

Atenção: esse artigo tem um vídeo complementar. Clique e assista!

De que se trata o artigo:

Neste artigo serão exibidos casos comuns onde aplicações poderiam ter um desempenho melhor, procurando sempre mostrar ao leitor dicas para serem aplicadas no dia a dia.

Em que situação o tema é útil:

Os computadores, hoje em dia, possuem processadores com mais de um núcleo. Logo, é importante aproveitar todo esse poder de processamento de maneira eficiente, seja economizando ciclos de execução ou distribuindo as tarefas entre os núcleos.

Resumo DevMan:

Durante o desenvolvimento de aplicações, nem sempre é possível escrever código tão eficiente quanto gostaríamos, seja por falta de tempo ou conhecimento. Pensando nisso, neste artigo serão abordadas dicas simples e que fazem a diferença quando o assunto é desempenho.

Nos dias de hoje, os servidores que rodam aplicações desenvolvidas por nós dificilmente terão menos de dois núcleos. Pensando nisso, é importante escrever softwares que saibam lidar com esse poder de processamento, e o Java, por exemplo, possui uma excelente API para tratamento de concorrência entre threads.

Economizar processamento é outro assunto importante, principalmente se o aplicativo for web, pois com uma quantidade de processamento menor, o software fica ocupado por menos tempo e consequentemente o usuário final não fica esperando uma reposta por um longo período.

Neste contexto, no decorrer deste artigo serão exibidos casos recorrentes do dia a dia de desenvolvimento e que fazem toda a diferença quando se precisa economizar tempo de processamento ou aproveitar melhor o que a máquina tem a lhe oferecer.

StringBuilder, StringBuffer e String

O primeiro tópico que vamos analisar é o caso onde a concatenação de Strings se faz necessária. Montar SQLs, escrever mensagens para os usuários da aplicação ou ainda um texto que será gravado em um arquivo são necessidades comuns durante o desenvolvimento.

Dito isto, já é possível avançar para as possibilidades de concatenação de Strings. O Java nos fornece três classes para trabalharmos com String, são elas: StringBuilder, StringBuffer e String. Cada uma com uma particularidade em especial, e que será explicada no decorrer deste tópico.

StringBuilder foi desenhada para substituir a classe StringBuffer em casos onde não é necessária a sincronização entre threads, ou seja, onde não há acesso concorrente, o que é a maioria dos casos. Deste modo, quando possível, é recomendável o uso desta classe ao invés de StringBuffer.

Quando instâncias de uma classe X qualquer são seguras o suficiente para serem manipuladas entre threads sem perder ou sobrescrever informações inseridas por outras threads, dizemos que estas instâncias são thread-safe.

Os principais métodos das classes StringBuilder e StringBuffer são append() e insert(). Estes foram sobrecarregados (vários métodos com o mesmo nome, recebendo parâmetros diferentes) para aceitarem qualquer tipo de dado que for informado por parâmetro.

Dito isto, agora exploraremos os meios de concatenação de Strings, começando pelo operador +. Este, quando usado, conforme exemplo da Listagem 1, faz com que o Java crie uma instância da classe StringBuilder, invoque o método append() e em seguida o método toString().

Listagem 1. Concatenando Strings com o operador +.

  public class ConcatenandoString {
   
   public static void main(String[] args) {
    String texto = “texto”;
    texto += “texto2”;
   }
   
  } 

Sempre que for necessário descobrir o que está acontecendo por debaixo dos panos, veja o bytecode gerado pelo compilador. O comando javap, seguido do parâmetro -c, mais o nome da classe, exibe o bytecode de um código Java. Ao executar este comando para o arquivo do exemplo de código da Listagem 1, temos saída apresentada na Listagem 2.

Listagem 2. Resultado da execução do comando javap -c StringTests.class

  joao@joao:~$ javap -c StringTests.class
  1.   11:     invokespecial #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  2.   14:     ldc    #29; //String texto2
  3.   16:     invokevirtual #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  4.   19:     invokevirtual #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 

Devido ao tamanho do bytecode gerado como resultado, algumas partes da saída do comando foram omitidas e também foi adicionada uma numeração em negrito no início das linhas para facilitar o entendimento.

Na linha 1, uma instância da classe StringBuilder foi criada. Na linha 2, uma String com o valor “texto2” foi criada. Na linha 3, o método append() foi invocado. Na linha 4, o método toString(). Ou seja, para cada concatenação feita em uma String, serão executadas quatro operações.

Em uma demonstração pequena como essa, não faz muito sentido instanciar a classe StringBuilder e concatenar as Strings por meio do método append(). No entanto, tenha em mente que a cada concatenação com o operador + acontecerá os passos explicados acima.

Sendo assim, várias instâncias de StringBuilder serão criadas, e isto é mais custoso para o servidor processar do que apenas uma, que seria o caso para quando se faz a concatenação por meio do método append().

Vamos então a um exemplo prático. Suponha que em um sistema existe uma página com uma tabela listando todos os Produtos cadastrados em um banco de dados, e existe um link nesta mesma página que exporta este relatório para um arquivo texto no formato .csv. Na Listagem 3 é possível ver o código da entidade Produto que terá seus valores exportados.

Listagem 3. Código da entidade Produto.

  public class Produto {
   
   private Long id;
   private Long numero;
   private String nome;
   private String descricao;
   private Integer quantidade;
   
   // getters e setters omitidos...
   
  } 

No entanto, antes de escrever o relatório no arquivo é necessário percorrer a lista de produtos e montar uma String com os produtos e seus campos separados por ponto e vírgula (“;”). Na Listagem 4 é possível visualizar o código que percorre esta lista.

"

A exibição deste artigo foi interrompida :(
Este post está disponível para assinantes MVP

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?