La synchronisation de l'accès à SimpleDateFormat
La javadoc de SimpleDateFormat états qui SimpleDateFormat n'est pas synchronisé.
"Formats de Date ne sont pas synchronisés. Il
est recommandé de créer des
format instances pour chaque thread. Si
plusieurs threads accèdent à un format
en même temps, elle doit être synchronisée
en externe."
Mais quelle est la meilleure approche à l'aide d'une instance de SimpleDateFormat dans un environnement multithread. Voici quelques options que j'ai pensé, j'ai utilisé les options 1 et 2 dans le passé, mais je suis curieux de savoir si il ya des meilleures alternatives ou laquelle de ces options serait d'offrir le meilleur de la performance et de la concurrence.
Option 1: Créer des instances locales lorsque requis
public String formatDate(Date d) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(d);
}
Option 2: Créer une instance de SimpleDateFormat comme une variable de classe, mais de synchroniser l'accès à elle.
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public String formatDate(Date d) {
synchronized(sdf) {
return sdf.format(d);
}
}
Option 3: Créer 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);
}
- +1 pour soulever cette question. Beaucoup de gens pensent que SimpleDateFormat est thread-safe (je vois hypothèses partout).
- Pour plus d'informations sur le ThreadLocal approche, voir: javaspecialists.eu/archive/Issue172.html
- Et pourquoi, voir à cette question: stackoverflow.com/questions/6840803/...
- Avez-vous tort sauté "statique" mot clé dans l'Option 2?
Vous devez vous connecter pour publier un commentaire.
La création de SimpleDateFormat est cher. Ne pas l'utiliser sauf si c'est fait rarement.
OK si vous pouvez vivre avec un peu de blocage. Utiliser si formatDate() n'est pas beaucoup utilisée.
Option la plus rapide SI vous réutilisez des threads (le pool de thread). Utilise plus de mémoire que 2. et a plus de démarrage de frais généraux.
Pour des applications à la fois 2. et 3. sont des options viables. Qui est le meilleur pour votre cas dépend de votre cas d'utilisation. Méfiez-vous de l'optimisation prématurée. Seulement le faire si vous croyez que c'est un problème.
Pour les bibliothèques qui serait utilisé par le 3e partie, je serais d'utiliser l'option 3.
SimpleDateFormat
comme une variable d'instance, alors nous pouvons utilisersynchronized block
à faire thread-safe. Mais sonar affiche d'avertissement squid-AS2885 . Est-il possible de résoudre sonar problème?L'autre option est Commons Lang FastDateFormat mais vous ne pouvez l'utiliser pour le formatage de la date et de ne pas l'analyse.
Contrairement à Joda, il peut fonctionner comme une baisse-dans le remplacement pour la mise en forme.
(Mise à jour: Depuis la v3.3.2, FastDateFormat peut produire un FastDateParser, qui est un "thread-safe" de remplacement pour SimpleDateFormat)
FastDateFormat
aparse()
méthodeSi vous êtes à l'aide de Java 8, vous pouvez utiliser
java.temps.format.DateTimeFormatter
:par exemple:
Commons Lang 3.x a maintenant FastDateParser ainsi que FastDateFormat. Il est thread-safe et plus rapide que SimpleDateFormat. Il utilise également le même format/parse modèle de spécifications SimpleDateFormat.
Ne pas utiliser SimpleDateFormat, utilisez joda-time DateTimeFormatter à la place. C'est un peu plus strictes dans l'analyse de côté et n'est donc pas tout à fait une chute de remplacement pour SimpleDateFormat, mais joda-time est beaucoup plus en même temps convivial en termes de sécurité et de performance.
Je dirais, de créer un simple wrapper classe SimpleDateFormat qui synchronise l'accès à l'parse() et le format() et peut être utilisé comme un remplacement. Plus infaillible que votre option #2, moins encombrant que votre option #3.
Semble faire SimpleDateFormat non synchronisées était une mauvaise décision de conception sur la partie de l'API Java concepteurs; je doute que quiconque s'attend à ce format() et parse() pour doivent être synchronisés.
Une autre option est de garder les instances dans un thread-safe file d'attente:
La taille de dateFormatQueue devrait être quelque chose de proche de l'estimation du nombre de threads qui peuvent régulièrement appel à cette fonction en même temps.
Dans le pire des cas où plus de threads que ce nombre ne fait utiliser toutes les instances simultanément, des SimpleDateFormat instances seront créées qui ne peuvent pas être retournés à dateFormatQueue parce qu'il est plein. Cela ne génère pas une erreur, il va juste subir la peine de la création de certains SimpleDateFormat qui sont utilisés qu'une seule fois.
J'ai juste mis en œuvre des ce avec l'Option 3, mais fait quelques modifications de code:
Vous pouvez définir des paramètres régionaux et fuseau horaire, sauf si vous voulez vraiment les paramètres par défaut (par défaut sont très enclins à faire des erreurs avec Java)
Imaginez que votre application a un thread. Pourquoi voudriez-vous synchroniser l'accès à SimpleDataFormat variable alors?