El javadoc para SimpleDateFormat indica que SimpleDateFormat no está sincronizado.
"Los formatos de fecha no están sincronizados. Se recomienda crear instancias de formato independientes para cada subproceso. Si varios subprocesos acceden a un formato al mismo tiempo, debe sincronizarse externamente".
Pero, ¿cuál es el mejor enfoque para usar una instancia de SimpleDateFormat en un entorno de subprocesos múltiples? Aquí hay algunas opciones en las que he pensado, he usado las opciones 1 y 2 en el pasado, pero tengo curiosidad por saber si hay mejores alternativas o cuál de estas opciones ofrecería el mejor rendimiento y concurrencia.
Opción 1: crear instancias locales cuando sea necesario
public String formatDate(Date d) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(d);
}
Opción 2: Cree una instancia de SimpleDateFormat como una variable de clase pero sincronice el acceso a ella.
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public String formatDate(Date d) {
synchronized(sdf) {
return sdf.format(d);
}
}
Opción 3: cree un ThreadLocal para almacenar una instancia diferente de SimpleDateFormat para cada hilo.
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);
}
Respuestas:
Crear SimpleDateFormat es caro . No use esto a menos que se haga con poca frecuencia.
Está bien si puedes vivir con un poco de bloqueo. Úselo si formatDate () no se usa mucho.
La opción más rápida SI reutiliza subprocesos ( grupo de subprocesos ). Utiliza más memoria que 2. y tiene una sobrecarga de inicio más alta.
Para aplicaciones, tanto 2. como 3. son opciones viables. Cuál es mejor para su caso depende de su caso de uso. Tenga cuidado con la optimización prematura. Solo hazlo si crees que esto es un problema.
Para las bibliotecas que serían utilizadas por terceros, usaría la opción 3.
fuente
SimpleDateFormat
como una variable de instancia, podemos usarsynchronized block
para hacerlo seguro para subprocesos. Pero el sonar muestra una advertencia de calamar-AS2885 . ¿Hay alguna forma de resolver el problema de la sonda?La otra opción es Commons Lang FastDateFormat, pero solo puede usarla para formatear la fecha y no para analizar.
A diferencia de Joda, puede funcionar como un reemplazo directo del formateo. (Actualización: desde v3.3.2, FastDateFormat puede producir un FastDateParser , que es un reemplazo seguro para subprocesos para SimpleDateFormat)
fuente
FastDateFormat
tieneparse()
métodoSi está utilizando Java 8, es posible que desee utilizar
java.time.format.DateTimeFormatter
:p.ej:
fuente
Commons Lang 3.x ahora tiene FastDateParser y FastDateFormat. Es seguro para subprocesos y más rápido que SimpleDateFormat. También utiliza las mismas especificaciones de patrón de formato / análisis que SimpleDateFormat.
fuente
No use SimpleDateFormat, use DateTimeFormatter de joda-time en su lugar. Es un poco más estricto en el lado del análisis y, por lo tanto, no es un reemplazo para SimpleDateFormat, pero joda-time es mucho más amigable en términos de seguridad y rendimiento.
fuente
Yo diría que cree una clase contenedora simple para SimpleDateFormat que sincronice el acceso a parse () y format () y pueda usarse como un reemplazo directo. Más infalible que su opción # 2, menos engorrosa que su opción # 3.
Parece que hacer que SimpleDateFormat no esté sincronizado fue una mala decisión de diseño por parte de los diseñadores de la API de Java; Dudo que alguien espere que format () y parse () necesiten sincronizarse.
fuente
Otra opción es mantener las instancias en una cola segura para subprocesos:
El tamaño de dateFormatQueue debe ser algo cercano al número estimado de subprocesos que pueden llamar a esta función de forma rutinaria al mismo tiempo. En el peor de los casos, donde más subprocesos que este número realmente usan todas las instancias al mismo tiempo, se crearán algunas instancias de SimpleDateFormat que no se pueden devolver a dateFormatQueue porque está lleno. Esto no generará un error, solo incurrirá en la penalización de crear algunos SimpleDateFormat que se usan solo una vez.
fuente
Acabo de implementar esto con la Opción 3, pero hice algunos cambios en el código:
Es posible que desee establecer la configuración regional y la zona horaria a menos que realmente desee la configuración predeterminada (los valores predeterminados son muy propensos a errores con Java)
fuente
Imagina que tu aplicación tiene un hilo. Entonces, ¿por qué sincronizaría el acceso a la variable SimpleDataFormat?
fuente