SimpleDateFormat,你线程不安全

      由于项目是运行在多线程环境下的,SimpleDateFormat对于日期的转换就出问题了。昨天测试部邮件通知我们日志的开始时间大于结束时间的时候我头都大了。经查找,发现是由于SimpleDateFormat线程不安全引起的。哎,以前一直在用这个类,从来没关注过。

现将测试代码发上。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang.time.FastDateFormat;

public class Main {
	private static final DateFormatUtils dateUtil = new DateFormatUtils();
	private static final SimpleDateFormat sdf = new SimpleDateFormat(
			"yyyy-MM-dd HH:mm:ss.SSS");
	private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();

	private SimpleDateFormat getFormat() {
		SimpleDateFormat sdf = threadLocal.get();
		if (sdf == null) {
			sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
			threadLocal.set(sdf);
		}
		return sdf;
	}

	public void foo(Date d1, Date d2) throws ParseException {
		String sd1 = getFormat().format(d1);
		String sd2 = getFormat().format(d2);
		Date dd1 = getFormat().parse(sd1);
		Date dd2 = getFormat().parse(sd2);
		if (dd1.getTime() - dd2.getTime() > 0) {
			System.err.println("Error:" + sd1 + ">" + sd2);
		}
	}

	public void foo2(Date d1, Date d2) throws ParseException {
		String sd1 = DateFormatUtils.format(d1, "yyyy-MM-dd HH:mm:ss.SSS");
		String sd2 = DateFormatUtils.format(d2, "yyyy-MM-dd HH:mm:ss.SSS");
		Date dd1 = DateUtils.parseDate(sd1,
				new String[] { "yyyy-MM-dd HH:mm:ss.SSS" });
		Date dd2 = DateUtils.parseDate(sd1,
				new String[] { "yyyy-MM-dd HH:mm:ss.SSS" });
		if (dd1.getTime() - dd2.getTime() > 0) {
			System.err.println("Error:" + sd1 + ">" + sd2);
		}

	}

	public static void main(String[] args) throws ParseException {
		Main m = new Main();
		Thread thread1 = new Thread(new Thread1(m));
		thread1.start();
		Thread thread2 = new Thread(new Thread1(m));
		thread2.start();
	}

}

 

两个线程:

import java.text.ParseException;
import java.util.Date;
public class Thread1 implements Runnable{
	private Main main;
	 public Thread1(Main main){
		 this.main = main;
	 }
	  public void run() {
	    for(;;){
	    	try {
				main.foo(new Date(), new Date());
			} catch (ParseException e) {
				e.printStackTrace();
			}
	    }
	  }
	}

 

import java.text.ParseException;
import java.util.Date;
public class Thread2 implements Runnable{
	private Main main;
	 public Thread2(Main main){
		 this.main = main;
	 }
	  public void run() {
	    for(;;){
	    	try {
				main.foo2(new Date(), new Date());
			} catch (ParseException e) {
				e.printStackTrace();
			}
	    }
	  }
	}

 

      如上,如果Main类中foo方法使用静态常量sdf进行转换很多错误的打印语句。如果使用ThreadLocal类绑定SimpleDateFormat则可以解决线程不统一的问题。

        当然使用Apache提供的类DateFormatUtils以及DateUtils类进行日期的转换也可以解决线程的问题,如foo2方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值