Le javadoc pour SimpleDateFormat indique que SimpleDateFormat n'est pas synchronisé.
"Les formats de date ne sont pas synchronisés. Il est recommandé de créer des instances de format distinctes pour chaque thread. Si plusieurs threads accèdent à un format simultanément, il doit être synchronisé en externe."
Mais quelle est la meilleure approche pour utiliser une instance de SimpleDateFormat dans un environnement multithread. Voici quelques options auxquelles j'ai pensé, j'ai utilisé les options 1 et 2 dans le passé, mais je suis curieux de savoir s'il existe de meilleures alternatives ou laquelle de ces options offrirait les meilleures performances et la meilleure concurrence.
Option 1: créer des instances locales si nécessaire
public String formatDate(Date d) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(d);
}
Option 2: créez une instance de SimpleDateFormat en tant que variable de classe mais synchronisez l'accès à celle-ci.
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public String formatDate(Date d) {
synchronized(sdf) {
return sdf.format(d);
}
}
Option 3: créez un ThreadLocal pour stocker une instance différente de SimpleDateFormat pour chaque 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);
}
Réponses:
La création de SimpleDateFormat coûte cher . N'utilisez pas ceci à moins que ce ne soit fait rarement.
OK si vous pouvez vivre avec un peu de blocage. À utiliser si formatDate () n'est pas beaucoup utilisé.
Option la plus rapide SI vous réutilisez des threads ( pool de threads ). Utilise plus de mémoire que 2. et a une surcharge de démarrage plus élevée.
Pour les applications 2. et 3. sont des options viables. Ce qui convient le mieux à votre cas dépend de votre cas d'utilisation. Méfiez-vous des optimisations prématurées. Ne le faites que si vous pensez que c'est un problème.
Pour les bibliothèques qui seraient utilisées par des tiers, j'utiliserais l'option 3.
la source
SimpleDateFormat
comme variable d'instance, nous pouvons l'utilisersynchronized block
pour la rendre thread-safe. Mais le sonar affiche un avertissement squid-AS2885 . Existe-t-il un moyen de résoudre le problème du sonar?L'autre option est Commons Lang FastDateFormat, mais vous ne pouvez l'utiliser que pour le formatage de la date et non l'analyse.
Contrairement à Joda, il peut fonctionner comme un remplacement instantané pour le formatage. (Mise à jour: depuis la v3.3.2, FastDateFormat peut produire un FastDateParser , qui est un remplacement de thread-safe pour SimpleDateFormat)
la source
FastDateFormat
a également uneparse()
méthodeSi vous utilisez Java 8, vous souhaiterez peut-être utiliser
java.time.format.DateTimeFormatter
:par exemple:
la source
Commons Lang 3.x a maintenant FastDateParser ainsi que FastDateFormat. Il est thread-safe et plus rapide que SimpleDateFormat. Il utilise également les mêmes spécifications de format / modèle d'analyse que SimpleDateFormat.
la source
N'utilisez pas SimpleDateFormat, utilisez plutôt le DateTimeFormatter de joda-time. Il est un peu plus strict du côté de l'analyse et ne remplace donc pas SimpleDateFormat, mais joda-time est beaucoup plus convivial en termes de sécurité et de performances.
la source
Je dirais, créez une simple classe wrapper pour SimpleDateFormat qui synchronise l'accès à parse () et format () et peut être utilisée comme remplacement instantané. Plus infaillible que votre option n ° 2, moins lourde que votre option n ° 3.
On dirait que rendre SimpleDateFormat non synchronisé était une mauvaise décision de conception de la part des concepteurs d'API Java; Je doute que quiconque s'attende à ce que format () et parse () aient besoin d'être synchronisés.
la source
Une autre option consiste à conserver les instances dans une file d'attente thread-safe:
La taille de dateFormatQueue doit être quelque chose de proche du nombre estimé de threads qui peuvent régulièrement appeler cette fonction en même temps. Dans le pire des cas où plus de threads que ce nombre utilisent réellement toutes les instances simultanément, certaines instances SimpleDateFormat seront créées et ne pourront pas être renvoyées à dateFormatQueue car elle est pleine. Cela ne générera pas d'erreur, cela entraînera simplement la pénalité de créer un SimpleDateFormat qui ne sera utilisé qu'une seule fois.
la source
Je viens de l'implémenter avec l'option 3, mais j'ai apporté quelques modifications au code:
Vous pouvez définir les paramètres régionaux et le fuseau horaire à moins que vous ne souhaitiez vraiment les paramètres par défaut (les paramètres par défaut sont très sujets aux erreurs avec Java)
la source
Imaginez que votre application ait un thread. Pourquoi synchroniseriez-vous l'accès à la variable SimpleDataFormat alors?
la source