O javadoc para SimpleDateFormat afirma que SimpleDateFormat não está sincronizado.
"Os formatos de data não são sincronizados. É recomendado criar instâncias de formato separadas para cada thread. Se vários threads acessarem um formato simultaneamente, ele deve ser sincronizado externamente."
Mas qual é a melhor abordagem para usar uma instância de SimpleDateFormat em um ambiente multiencadeado. Aqui estão algumas opções que pensei, usei as opções 1 e 2 no passado, mas estou curioso para saber se há alternativas melhores ou qual dessas opções ofereceria o melhor desempenho e simultaneidade.
Opção 1: criar instâncias locais quando necessário
public String formatDate(Date d) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(d);
}
Opção 2: crie uma instância de SimpleDateFormat como uma variável de classe, mas sincronize o acesso a ela.
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public String formatDate(Date d) {
synchronized(sdf) {
return sdf.format(d);
}
}
Opção 3: Crie um ThreadLocal para armazenar uma instância diferente de SimpleDateFormat para cada thread.
private ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>();
public String formatDate(Date d) {
SimpleDateFormat sdf = tl.get();
if(sdf == null) {
sdf = new SimpleDateFormat("yyyy-MM-hh");
tl.set(sdf);
}
return sdf.format(d);
}
Respostas:
Criar SimpleDateFormat é caro . Não use isso, a menos que seja feito raramente.
Tudo bem se você conseguir viver com um pouco de bloqueio. Use se formatDate () não for muito usado.
A opção mais rápida SE você reutilizar threads ( pool de threads ). Usa mais memória do que 2. e tem maior sobrecarga de inicialização.
Para aplicações, 2. e 3. são opções viáveis. O que é melhor para o seu caso depende do seu caso de uso. Cuidado com a otimização prematura. Só faça isso se você acreditar que isso é um problema.
Para bibliotecas que seriam usadas por terceiros, eu usaria a opção 3.
fonte
SimpleDateFormat
como uma variável de instância, podemos usarsynchronized block
para torná-la segura para thread. Mas o sonar mostra o aviso squid-AS2885 . Existe alguma maneira de resolver o problema do sonar?A outra opção é Commons Lang FastDateFormat, mas você só pode usá-lo para formatação de data e não para análise.
Ao contrário do Joda, ele pode funcionar como um substituto imediato para a formatação. (Atualização: desde a v3.3.2, FastDateFormat pode produzir um FastDateParser , que é uma substituição de thread-safe drop-in para SimpleDateFormat)
fonte
FastDateFormat
temparse()
método tambémSe você estiver usando o Java 8, convém usar
java.time.format.DateTimeFormatter
:por exemplo:
fonte
Commons Lang 3.x agora tem FastDateParser, bem como FastDateFormat. É thread-safe e mais rápido do que SimpleDateFormat. Ele também usa as mesmas especificações de padrão de formato / análise como SimpleDateFormat.
fonte
Não use SimpleDateFormat, use DateTimeFormatter do joda-time. É um pouco mais rígido no lado da análise e, portanto, não é uma queda na substituição de SimpleDateFormat, mas o joda-time é muito mais amigável ao mesmo tempo em termos de segurança e desempenho.
fonte
Eu diria, crie uma classe de invólucro simples para SimpleDateFormat que sincronize o acesso a parse () e format () e possa ser usada como um substituto drop-in. Mais infalível do que a opção nº 2, menos complicado do que a opção nº 3.
Parece que tornar SimpleDateFormat dessincronizado foi uma má decisão de design por parte dos designers da API Java; Duvido que alguém espere que format () e parse () precisem ser sincronizados.
fonte
Outra opção é manter as instâncias em uma fila thread-safe:
O tamanho de dateFormatQueue deve ser algo próximo ao número estimado de threads que podem chamar essa função rotineiramente ao mesmo tempo. No pior caso, onde mais encadeamentos do que esse número realmente usam todas as instâncias simultaneamente, algumas instâncias SimpleDateFormat serão criadas, as quais não podem ser retornadas para dateFormatQueue porque está cheio. Isso não gerará um erro, apenas incorrerá na penalidade de criar alguns SimpleDateFormat que são usados apenas uma vez.
fonte
Acabei de implementar isso com a opção 3, mas fiz algumas alterações no código:
Você pode querer definir o local e o fuso horário, a menos que você realmente queira as configurações padrão (os padrões são muito sujeitos a erros com Java)
fonte
Imagine que seu aplicativo tenha um thread. Por que você sincronizaria o acesso à variável SimpleDataFormat então?
fonte