欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SimpleDateFormat的非线程安全问题 博客分类: java 基础  

程序员文章站 2024-03-22 20:34:52
...

由于SimpleDateFormat不是线程安全的,因此在多线程环境下,如果共用一个SimpleDateFormat实例,会出现线程安全问题。

例如,在解析excel里的日期字段时,会报以下异常:

java.lang.NumberFormatException: For input string: ".31023102EE22"

 

解决的办法(一):每一个线程都new 一个SimpleDateFormat对象,而不能将SimpleDateFormat放在类的静态变量里进行实例化:

	/**
	 * 格式化日期
	 * @param dateString
	 * @return
	 */
	private Date parseDate(String dateString) {
		Date date = null;
             SimpleDateFormat sdf = null;
		try {
			if(dateString.indexOf('-')>0) {
		            sdf = new SimpleDateFormat("yyyy-MM-dd");
		        } else if(dateString.indexOf('/')>0) {
		            sdf = new SimpleDateFormat("yyyy/MM/dd");
		        } else if(dateString.length()==8) {
		            sdf = new SimpleDateFormat("yyyyMMdd");
		        } 
			date = sdf.parse(dateString);
		} catch (ParseException e) {
			logger.error("Parse " + dateString + " error!", e);
		}
		return date;
	}

 

 

解决的办法(二):将SimpleDateFormat放在ThreadLocal里,然后每个线程自己获取:

 

//每一个线程
private static final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
 在使用的时候,从ThreadLocal里获取,这样就能保证线程安全了。
/**
	 * 格式化日期
	 * @param dateString
	 * @return
	 */
	private Date parseDate(String dateString) {
		Date date = null;
		try {
			SimpleDateFormat sdf = threadLocal.get(); // SimpleDateFormat非线程安全
			if (sdf == null){
				if(dateString.indexOf('-')>0) {
		            sdf = new SimpleDateFormat("yyyy-MM-dd");
		        } else if(dateString.indexOf('/')>0) {
		        	sdf = new SimpleDateFormat("yyyy/MM/dd");
		        } else if(dateString.length()==8) {
		        	sdf = new SimpleDateFormat("yyyyMMdd");
		        } 
				date = sdf.parse(dateString);
			}
		} catch (ParseException e) {
			logger.error("Parse " + dateString + " error!", e);
		}
		return date;
	}