8-05 2,611 views
在需要进行日期与字符串相互转换的类中,经常会声明一个静态的SimpleDateFormat变量,如下所示:
1 |
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") |
然后就可以直接使用sdf的format和parse方法进行日期与字符串的相互转换,但是SimpleDateFormat并不是线程安全的,我们使用如下代码验证SimpleDateFormat的线程安全问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class Test { private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private static String[] dates = new String[]{"2015-07-01 10:45:52", "2015-07-02 09:34:11", "2015-07-01 07:12:32", "2015-07-03 15:06:54", "2015-07-02 21:12:38", "2015-07-01 01:59:01", "2015-07-02 13:51:18", "2015-07-03 10:05:08"}; public static class MyThread extends Thread { public void run() { for (int i=0; i<100; i++) { try { System.out.println(Thread.currentThread().getName() + "\t" + sdf.format(sdf.parse(dates[new Random().nextInt(8)]))); } catch (Exception e) { e.printStackTrace(); } } } } public static void main(String[] args) throws ParseException { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); t1.start(); t2.start(); } } |
MyThread线程循环100次,每次从dates数组中随机取出一个日期字符串,依次进行parse和format操作后再输出最终的日期字符串,若声明一个MyThread线程运行,则输出如图所示:
输出的日期字符串都在dates数组中,说明parse和format操作均正常。若声明两个MyThread线程运行,则输出如图所示:
输出的日期字符串有不在dates数组中的,且还存在异常,说明parse和format操作并不是线程安全的。
在多线程下若要使用SimpleDateFormat,一种方法是每次进行日期与字符串转换时,声明一个SimpleDateFormat变量,但这样会产生过多的变量实例,另一种方法是使用ThreadLocal为每个线程保存一个SimpleDateFormat变量实例,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class DateUtil { private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>() { protected synchronized SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } }; public static SimpleDateFormat get() { return threadLocal.get(); } public static Date parse(String s) throws ParseException { return get().parse(s); } public static String format(Date d) { return get().format(d); } } |
同时修改MyThread,使用DateUtil进行日期与字符串转换,如下所示:
1 2 3 4 5 6 7 8 9 10 11 |
public static class MyThread extends Thread { public void run() { for (int i=0; i<100; i++) { try { System.out.println(Thread.currentThread().getName() + "\t" + DateUtil.format(DateUtil.parse(dates[new Random().nextInt(8)]))); } catch (Exception e) { e.printStackTrace(); } } } } |
再声明两个MyThread线程运行,则输出正常。
版权属于: 我爱我家
转载时必须以链接形式注明原始出处及本声明。
🙂