java time to date_Java时间格式Date和String互相转换

一 常用方案:SimpleDateFormat

public class TimeUtils {

public static String formatDate(Date date) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

return sdf.format(date);

}

public static Date parse(String strDate) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

try {

return sdf.parse(strDate);

} catch (ParseException e) {

e.printStackTrace();

}

return null;

}

二 出现的问题

每次调用方都要new SimpleDateFormat(),每次处理一个时间信息的时候,就需要创建一个SimpleDateFormat实例对象,然后再丢弃这个对象。大量的对象就这样被创建出来,占用大量的内存和 jvm空间

于是 那我就创建一个静态的simpleDateFormat实例

public class TimeUtils {

private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public static String formatDate(Date date) {

return sdf.format(date);

}

public static Date parse(String strDate) {

try {

return sdf.parse(strDate);

} catch (ParseException e) {

e.printStackTrace();

}

return null;

}

但是问题是:线程不安全,在format方法里,有这样一段代码:

private StringBuffer format(Date date, StringBuffer toAppendTo,

FieldDelegate delegate) {

calendar.setTime(date);

boolean useDateFormatSymbols = useDateFormatSymbols();

for (int i = 0; i < compiledPattern.length; ) {

int tag = compiledPattern[i] >>> 8;

int count = compiledPattern[i++] & 0xff;

if (count == 255) {

count = compiledPattern[i++] << 16;

count |= compiledPattern[i++];

}

switch (tag) {

case TAG_QUOTE_ASCII_CHAR:

toAppendTo.append((char)count);

break;

case TAG_QUOTE_CHARS:

toAppendTo.append(compiledPattern, i, count);

i += count;

break;

default:

subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);

break;

}

}

return toAppendTo;

}

calendar不是方法局部变量而是SimpleDateFormat类的全局变量,而这就是引发问题的根源。想象一下,在一个多线程环境下,有两个线程持有了同一个SimpleDateFormat的实例,分别调用format方法:

线程1调用format方法,改变了calendar这个字段。

中断来了。

线程2开始执行,它也改变了calendar。

又中断了。

线程1回来了,此时,calendar已然不是它所设的值,而是走上了线程2设计的道路。如果多个线程同时争抢calendar对象,则会出现各种问题,时间不对,线程挂死等等。

分析一下format的实现,我们不难发现,用到成员变量calendar,唯一的好处,就是在调用subFormat时,少了一个参数,却带来了这许多的问题。其实,只要在这里用一个局部变量,一路传递下去,所有问题都将迎刃而解。

三 解决办法:

1  SimpleDateFormat作为线程局部变量来使用。2使用对象锁,代码如下。3使用jodaTime(推荐)

public class TimeUtils {

private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public static String formatDate(Date date) {

synchronized(sdf){

return sdf.format(date);

}

}

public static Date parse(String strDate) {

synchronized(sdf){

try {

return sdf.parse(strDate);

} catch (ParseException e) {

e.printStackTrace();

}

return null;

}

}

四 jodaTime使用:

public class TimeUtils {

public static String formatDate(Date date) {

DateTime dateTime = new DateTime(date);

String formatStr = "yyyy-MM-dd HH:mm:ss";

return dateTime.toString(formatStr);

}

public static Date parse(String strDate) {

DateTimeFormatter dateTimeFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");

DateTime dateTime = DateTime.parse(strDate, dateTimeFormat);

dateTime = dateTime.plusDays(1);

return dateTime.toDate();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值