`
Ashton
  • 浏览: 32795 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

SimpleDateFormat

阅读更多

 

系统中对文档的处理有这么一个简单的过程

1.通过web service取出文档属性数据

2.对文档属性数据进行转化处理,其中有一项转化是把文档发布日期由一种显示格式转为另外一种显示格式,这个转化是不久前加上去的

3.根据文档发布日期对文档排序,将最新的文档放在前面

最近经常出现一种情况,经常会有非常旧的文档排在了前面,初步判断有两种可能性

1.排序算法有问题

2.日期格式有问题,没被正常解析

1个小时过去了,排序没问题,两个小时过去了,web service返回日期串是好的,但是发现一个奇怪的现象

日期2009-07-09 03:45:01 竟然被转化成了15 Mar 2015 03:45:01,并且这种现象貌似比较随机,大多说时候日期解析都是完全正确的2009-07-09 03:45:01 -> 09 Jul 2009 03:45:01

代码里挖呀挖,终于发现这么一行

 

public static final DateFormat DOCTIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

很明显,由于这个日期格式在很多地方会用到,写代码的为了统一也出于性能考虑创建了这么一个公有常量。而这么做是有代价的。

好了,切入正题。

我们经常会用SimpleDateFormat去做日期的解析和格式化,然而经常被忽略的一个事实是 SimpleDateFormat是非线程安全的。

且看下面一段代码, 

 

public class DateFormatTest {
	private static final DateFormat DOCTIME_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ExecutorService exec = Executors.newFixedThreadPool(30);
		for (int i=0; i<20; i++) {
			Runnable task = new Runnable(){
				@Override
				public void run() {
					Date date;
					try {
						date = DOCTIME_FORMAT.parse("07/11/2009 09:12:17");
						System.out.println(DOCTIME_FORMAT.format(date));
					} catch (ParseException e) {
						// ignore
					}
				}
			};
			exec.execute(task);
			}
		}
}

 

 我得到了这样的结果:

07/11/2009 09:12:17
07/01/1970 12:00:00
07/01/2009 12:12:17
07/11/2009 09:12:17

.....

 

本来这也不是什么大问题,非线程安全的类多了,问题是JDK1.4以前的文档里并没像说明HashMap一样说明该类是非线程安全的,JDK1.4以后的文档里最有有句说明,我们很多时候还是默认它是线程安全的了,因为我们用它的时候完全考虑的是怎样格式化或解析日期。这也提醒我们:

1.自己写公用类的时候,要对多线程调用情况下的后果在注释里进行明确说明

2.对线程环境下,对每一个共享的可变变量都要注意其线程安全性

 

问题找到了,得有方案不是,想来基本就下面几种办法:

1. 将

private static final DateFormat DOCTIME_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");

改为 

private static final String DOCTIME_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");

在需要用到DateFormat的地方新建一个实例,不管什么时候,将有线程安全问题的对象由共享变为局部私有都能避免多线程问题,不过也加重了创建对象的负担。

2. 将DateFormat放在ThreadLocal中

private static final ThreadLocal<DateFormat> DOCTIME_FORMAT = new ThreadLocal<DateFormat>() {
	protected DateFormat initialValue() {
	        return new SimpleDateFormat("MM/dd/yyyy hh:mm:ss");
	}
};

 使用ThreadLocal, 也是将共享变量变为独享,线程独享肯定能比方法独享并发环境能减少不少创建对象的开销

 

3. 使用Apache commons 里的FastDateFormat,宣称是既快又线程安全的SimpleDateFormat, 可惜它只能对日期进行format, 不能对日期串进行解析。

 

Over.

 

分享到:
评论

相关推荐

    JavaScript实现的SimpleDateFormat

    在JavaScript中,没有内置的`SimpleDateFormat`类,它是一个Java中的类,用于日期和时间的格式化。然而,由于JavaScript在处理日期时的功能相对有限,开发者常常需要自定义函数或者使用第三方库来实现类似的功能。这...

    有关SimpleDateFormat的常用方法说明

    ### SimpleDateFormat的常用方法说明 #### 一、简介 `SimpleDateFormat`是Java中用于格式化日期和时间的一个类。它允许我们自定义日期/时间的显示格式,这在实际开发中非常有用,尤其是在处理不同地区或语言环境下...

    java 使用SimpleDateFormat类获取系统的当前时间

    在Java编程语言中,`SimpleDateFormat` 是一个非常重要的日期和时间格式化工具类,它允许程序员以特定的模式来解析和格式化日期。当我们需要从系统获取当前时间并按照自定义格式显示时,`SimpleDateFormat` 就派上了...

    java SimpleDateFormat &Calendar

    在Java编程语言中,`SimpleDateFormat`和`Calendar`是两个重要的日期和时间处理类,它们在处理日期格式化、解析以及日期计算方面扮演着重要角色。本文将深入探讨这两个类的功能、用法以及它们之间的关系。 `...

    高并发之-SimpleDateFormat类的线程安全问题和解决方案.docx

    SimpleDateFormat类的线程安全问题和解决方案 SimpleDateFormat类的线程安全问题 SimpleDateFormat类是Java提供的日期时间转化类,用于将日期和时间类型的数据进行解析和格式化。在Java开发中,SimpleDateFormat类...

    java SimpleDateFormat 显示于系统时间不符

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); date.setTime(time); System.out.println(sdf.format(date)); 发现时间于想要的时间不符,请运行Time.reg文件

    simpleDateFormat是线程不安全的

    在Java编程语言中,`SimpleDateFormat`类是一个广泛使用的日期时间格式化工具,但它的线程安全性是一个常常被开发者忽视的问题。标题指出的"simpleDateFormat是线程不安全的",意味着在多线程环境下,如果多个线程...

    深入理解Java:SimpleDateFormat安全的时间格式化

    "深入理解Java:SimpleDateFormat安全的时间格式化" 在Java中,SimpleDateFormat是一个非常常用的类,用来对日期字符串进行解析和格式化输出。但是,如果使用不小心会导致非常微妙和难以调试的问题,因为DateFormat...

    SimpleDateFormat使用详解

    SimpleDateFormat 使用详解 SimpleDateFormat 是 Java 中的一个日期和时间格式化类,它继承自 DateFormat 类。SimpleDateFormat 允许用户以各种方式格式化日期和时间,例如以年、月、日、时、分、秒等不同的格式来...

    由浅入深解析 SimpleDateFormat

    SimpleDateFormat 详解 SimpleDateFormat 是 Java 语言中的一种日期和时间格式化类,用于将日期和时间格式化为字符串或将字符串解析为日期和时间。它是 DateFormat 的子类,继承自 java.text.Format。 ...

    SimpleDateFormat格式化日期

    日期操作。。。基础的SimpleDateFormat格式化日期!!操作!》初级学习代码

    ThreadLocal:如何优雅的解决SimpleDateFormat多线程安全问题

    目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug的原因如何解决SimpleDateFormat多线程安全问题局部变量使用...

    创建SimpleDateFormat对象,确定日期被格式化的格式.txt

    1.创建SimpleDateFormat对象,确定日期被格式化的格式 2.使用循环,在循环中调用Thread的sleep方法,让线程休眠1s后打印当前时间的字符串

    SimpleDateFormat线程不安全的5种解决方案.docx

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss"); // 创建时间对象 Date date = new Date(finalI * 1000); // 执行时间格式化并打印结果 System.out.println(simpleDateFormat.format(date...

    Java 实例 - 格式化时间SimpleDateFormat使用源代码-详细教程.zip

    在Java编程语言中,`SimpleDateFormat`是日期和时间格式化的关键工具,它允许程序员将日期和时间对象转换为字符串,以及将字符串解析回日期对象。这个详细教程将引导你了解如何有效地使用`SimpleDateFormat`类。以下...

    关于SimpleDateFormat的非线程安全问题及其解决方案.docx

    ### 关于SimpleDateFormat的非线程安全问题及其解决方案 #### 一、问题介绍 在Java开发过程中,`SimpleDateFormat`是被广泛使用的日期格式化工具类。然而,在多线程环境下,`SimpleDateFormat`存在非线程安全的...

    第五章.常用类.java.API概述——Date类,Calendar类,SimpleDateFormat类,Big.pdf

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); String dateString = formatter.format(new Date()); // 将当前日期格式化为字符串 Date parsedDate = formatter.parse(dateString); // 将字符...

    日期操作类(DateFormat、SimpleDateFormat)

    NULL 博文链接:https://chaoyi.iteye.com/blog/2082317

    Java SimpleDateFormat中英文时间格式化转换详解

    Java SimpleDateFormat中英文时间格式化转换详解 本文主要为大家详细介绍了Java SimpleDateFormat中英文时间格式化转换的知识点,包括日期和时间模式的设定、SimpleDateFormat的使用、日期和时间格式的转换等。 ...

Global site tag (gtag.js) - Google Analytics