segunda-feira, 13 de novembro de 2017

Problemas no uso do método System.currentTimeMillis() e uso do método System.nanoTime() na linguagem Java



INTRODUÇÃO

No desenvolvimento de sistemas usando a linguagem Java, é corriqueiro o uso do método de obter a quantidade de milissegundos do tempo atual (contando desde 1970).
Mas nesse artigo mostraremos problemas na chamada sucessiva desse método (que retorna o mesmo valor, como o tempo não "andasse") e possível solução para contornar os problemas.


PROBLEMA

Ao executarmos o seguinte código Java:



import java.text.SimpleDateFormat;
import java.util.Calendar;

public class TesteTempos {

    public static void main(String[] args) {
       
         final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmssS");

         final long time1 = System.currentTimeMillis();
         final long time2 = System.currentTimeMillis();
       
         final long nano1 = System.nanoTime();
         final long nano2 = System.nanoTime();
       
         final String txt1 = sdf.format(Calendar.getInstance().getTime());
         final String txt2 = sdf.format(Calendar.getInstance().getTime());
       
         System.out.println(time1);
         System.out.println(time2);
         System.out.println();
         System.out.println(nano1);
         System.out.println(nano2);
         System.out.println();
         System.out.println(txt1);
         System.out.println(txt2);
    }
}



Resultado (no console):

1510339299662
1510339299662

2068554850479041
2068554850479809

20171110_164139662
20171110_164139663


Note que as duas chamadas de System.currentTimeMillis() geram o mesmo valor. Isso é ruim num processamento num servidor JavaEE (por exemplo) aonde queremos tempos diferentes e não iguais! Se temos tempos iguais, nosso código pode dar erros em tempo de execução em alguma lógica que obrigue ser diferente (Exemplo: uso da data como parte da chave primária composta de um banco de dados).


SOLUÇÃO

Usar a chamada System.nanoTime() para gerar valores sempre distintos caso necessitamos (por exemplo, queremos inserir dois registros no banco de dados, sendo que esses tempos são parte de chave primária composta da tabela do banco de dados). Nesse caso, evitamos que a JVM retorne valores iguais!

Note também que a chamada a Calendar.getInstance().getTime() tem praticamente o mesmo efeito da chamada System.currentTimeMillis(), mas a diferença de 1 milissegundos está no fato no tempo de formatação da data pelo objeto da classe java.text.SimpleDateFormat.


CONCLUSÃO

Nesse artigo mostramos problemas no uso sucessivo da chamada System.currentTimeMillis() e maneiras de contorná-los! Em muitos casos envolvendo regras de negócio que necessitem chamadas sucessivas de tempos atuais, mas que retornem valores distintos, importante ter atenção e usar o método System.nanTime().