System.currentTimeMillis () vs. new Date () vs. Calendar.getInstance (). GetTime ()

238

Em Java, quais são as implicações de desempenho e recursos do uso

System.currentTimeMillis() 

vs.

new Date() 

vs.

Calendar.getInstance().getTime()

Pelo que entendi, System.currentTimeMillis()é o mais eficiente. No entanto, na maioria das aplicações, esse valor longo precisaria ser convertido em uma Data ou em um objeto semelhante para fazer algo significativo para os seres humanos.

Vihung
fonte

Respostas:

241

System.currentTimeMillis()é obviamente o mais eficiente, pois nem sequer cria um objeto, mas na new Date()verdade é apenas um invólucro fino por muito tempo, portanto não fica muito atrás. Calendarpor outro lado, é relativamente lento e muito complexo, pois precisa lidar com a complexidade considerável e todas as peculiaridades inerentes às datas e horas (anos bissextos, horário de verão, fusos horários etc.).

Geralmente, é uma boa idéia lidar apenas com registros de data e hora longos Dateno seu aplicativo e usar somente Calendarquando você realmente precisar executar cálculos de data / hora ou formatar datas para exibi-las ao usuário. Se você precisar fazer muito disso, provavelmente usar o Joda Time é uma boa ideia, para uma interface mais limpa e melhor desempenho.

Michael Borgwardt
fonte
2
Qual é a diferença entre timestamp e currentMillis?
pinkpanther
1
@pinkpanther: "timestamp" é normalmente usado para descrever um número inteiro / comprimento que descreve um ponto no tempo quando interpretado como segundos ou milissegundos desde o início de uma "época". Em outras palavras, currentTimeMillis () retorna um carimbo de data / hora.
Michael Borgwardt
42

Olhando para o JDK, o construtor mais interno de Calendar.getInstance()tem o seguinte:

public GregorianCalendar(TimeZone zone, Locale aLocale) {
    super(zone, aLocale);
    gdate = (BaseCalendar.Date) gcal.newCalendarDate(zone);
    setTimeInMillis(System.currentTimeMillis());
}

então ele já faz automaticamente o que você sugere. O construtor padrão da data mantém isso:

public Date() {
    this(System.currentTimeMillis());
}

Portanto, realmente não há necessidade de obter a hora do sistema especificamente, a menos que você queira fazer algumas contas com ela antes de criar seu objeto Calendário / Data. Também tenho que recomendar o joda-time para substituir as próprias classes de calendário / data do Java se seu objetivo é trabalhar muito com os cálculos de data.

Esko
fonte
22

Se você estiver usando uma data, recomendo fortemente que você use jodatime, http://joda-time.sourceforge.net/ . Usar System.currentTimeMillis()campos que são datas parece uma péssima idéia, pois você terá muito código inútil.

Tanto a data quanto o calendário são gravados com seriedade, e o Google Agenda é definitivamente o pior artista de todos.

Eu recomendo que você use System.currentTimeMillis()quando estiver operando com milissegundos, por exemplo, como este

 long start = System.currentTimeMillis();
    .... do something ...
 long elapsed = System.currentTimeMillis() -start;
krosenvold
fonte
28
Eu queria comentar sobre isso porque seu exemplo é exatamente uma das coisas para as quais você NÃO deve usar System.currentTimeMillis (); como não é uma fonte de relógio monotônico, não é possível calcular com confiabilidade o tempo decorrido. Se o relógio do sistema for alterado enquanto o código em execução estiver sendo executado, você obterá resultados estranhos (por exemplo, negativos). Em uso lugar System.nanoTime (), que é monótona , se o sistema oferece suporte subjacentes a tal fonte de relógio (ver bugs.java.com/bugdatabase/view_bug.do?bug_id=6458294 )
rem
System.currentTimeMillis em si não é afetado pelo fuso horário. Alterar a hora do sistema afetará System.nanotime da mesma maneira que System.currentTimeMillis
Viktor
12

Prefiro usar o valor retornado por System.currentTimeMillis()para todos os tipos de cálculos e usar apenas Calendarou Datese realmente preciso exibir um valor lido por humanos. Isso também impedirá 99% dos erros do horário de verão. :)

Bombe
fonte
12

Na minha máquina, tentei verificar. Meu resultado:

Calendar.getInstance (). GetTime () (* 1000000 vezes) = 402ms
new Date (). getTime (); (* 1000000 vezes) = 18 ms
System.currentTimeMillis () (* 1000000 vezes) = 16ms

Não se esqueça do GC (se você usa Calendar.getInstance()ou new Date())

Puzirki
fonte
1
maravilha se haverá alguma diferença se muitos segmentos chamar o mesmo entre outras transformações
tgkprog
7

Dependendo do seu aplicativo, você pode considerar o uso System.nanoTime().

MykennaC
fonte
Porque, sua pergunta foi sobre recursos e desempenho, nanoTime () usa mais recursos
WolfmanDragon
Eu mencionei isso porque é uma opção que ninguém mais sugeriu. O pôster não especificou uma plataforma. O bug do SDN 6876279 sugere que currentTimeMillis () e nanoTime () executam o mesmo em algumas versões do JDK. O pôster também não especificou suas necessidades de precisão, para as quais a lista original pode ser inadequada.
MykennaC
4
Por mais tarde que possa ser, todos os exemplos da pergunta têm uma noção absoluta de que horas são, por exemplo. 1.348.770.313.071 milis desde o início da época do Unix. O tempo que nanoTimeretorna é relativo (geralmente para o início do programa) e seria absurdo se você tentasse transformá-lo em uma data.
Dunes
sim, mas você pode armazenar currentTimeilli e nano em algum código estático no início do programa e usá-los como compensações para obter um nano preciso do milli usando um duplo var = currentTimeStart - nanoTimeStart + nanoTimeNow
tgkprog
3

Eu tentei isso:

        long now = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            new Date().getTime();
        }
        long result = System.currentTimeMillis() - now;

        System.out.println("Date(): " + result);

        now = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            System.currentTimeMillis();
        }
        result = System.currentTimeMillis() - now;

        System.out.println("currentTimeMillis(): " + result);

E o resultado foi:

Data (): 199

currentTimeMillis (): 3

wiji
fonte
4
Esta é uma micro referência e você deve ter cuidado para confiar nos resultados que obtém. Dê uma olhada em stackoverflow.com/questions/504103/… .
Axel
1
Esse benchmark não é significativo, ou melhor, mostra que o sistema operacional em Java é importante. Executei o mesmo benchmark em uma dúzia de vezes em loop (movendo a inicialização de "now" e "result" para fora do loop) e tive diferenças interessantes a cada execução: Date (): 322 a 330; currentTimeMillis (): 319 a 322. Em algumas outras execuções, tive Date (): 312 a 318; currentTimeMillis (): 324 a 335. Então, IMHO são bastante equivalentes, em casos reais (também olhando para a fonte do Date). JFYI, eu usei o Java7 no Ubuntu.
Sampisa
0

System.currentTimeMillis() é obviamente o mais rápido porque é apenas uma chamada de método e nenhum coletor de lixo é necessário.

Ramon
fonte
14
Sua resposta não tem valor, pois é apenas um subconjunto da resposta aprovada anteriormente. Você deve tentar não responder dessa maneira, especialmente não considerando que é uma pergunta muito antiga, com uma resposta de qualidade já existente.
Nicklas Gnejs Eriksson
1
Em segundo lugar, o coletor de lixo não é necessário para objetos de curto prazo no espaço Eden de qualquer maneira.
Niels Bech Nielsen