码迷,mamicode.com
首页 > 编程语言 > 详细

SimpleDateFormat线程不安全(转)

时间:2014-10-31 09:58:07      阅读:287      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   color   ar   使用   java   for   

 

 

 有三种方法可以解决以上安全问题。
  1).使用同步

 1 package com.bijian.study.date;
 2 
 3 import java.text.ParseException;
 4 import java.text.SimpleDateFormat;
 5 import java.util.Date;
 6 
 7 public class DateUtil02 implements DateUtilInterface {
 8 
 9     private SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
10     
11     @Override
12     public void format(Date date) {
13         System.out.println(dateformat.format(date));
14     }
15 
16     @Override
17     public void parse(String str) {
18         try {
19             synchronized(dateformat){
20                 System.out.println(dateformat.parse(str));
21             }
22         } catch (ParseException e) {
23             e.printStackTrace();
24         }
25     }
26 }


修改DateMainTest.java的DateUtilInterface dateUtil = new DateUtil01();为DateUtilInterface dateUtil = new DateUtil02();测试OK。

        不过,当线程较多时,当一个线程调用该方法时,其他想要调用此方法的线程就要block,这样的操作也会一定程度上影响性能。

 

  2).每次使用时,都创建一个新的SimpleDateFormat实例

 1 package com.bijian.study.date;
 2 
 3 import java.text.ParseException;
 4 import java.text.SimpleDateFormat;
 5 import java.util.Date;
 6 
 7 public class DateUtil03 implements DateUtilInterface {
 8 
 9     @Override
10     public void format(Date date) {
11         
12         SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
13         System.out.println(dateformat.format(date));
14     }
15 
16     @Override
17     public void parse(String str) {
18         try {
19             SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
20             System.out.println(dateformat.parse(str));
21         } catch (ParseException e) {
22             e.printStackTrace();
23         }
24     }
25 }

修改DateMainTest.java的DateUtilInterface dateUtil = new DateUtil02();为DateUtilInterface dateUtil = new DateUtil03();测试OK。

  

  3).借助ThreadLocal对象每个线程只创建一个实例

     借助ThreadLocal对象每个线程只创建一个实例,这是推荐的方法

     对于每个线程SimpleDateFormat不存在影响他们之间协作的状态,为每个线程创建一个SimpleDateFormat变量的拷贝或者叫做副本,代码如下:

 1 package com.bijian.study.date;
 2 
 3 import java.text.DateFormat;
 4 import java.text.ParseException;
 5 import java.text.SimpleDateFormat;
 6 import java.util.Date;
 7 
 8 public class DateUtil04 implements DateUtilInterface {
 9 
10     private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
11 
12     // 第一次调用get将返回null
13     private static ThreadLocal threadLocal = new ThreadLocal(){
14         protected Object initialValue() {  
15             return null;//直接返回null  
16         } 
17     };
18     
19     // 获取线程的变量副本,如果不覆盖initialValue,第一次get返回null,故需要初始化一个SimpleDateFormat,并set到threadLocal中
20     public static DateFormat getDateFormat() {
21         DateFormat df = (DateFormat) threadLocal.get();
22         if (df == null) {
23             df = new SimpleDateFormat(DATE_FORMAT);
24             threadLocal.set(df);
25         }
26         return df;
27     }
28 
29     @Override
30     public void parse(String textDate) {
31 
32         try {
33             System.out.println(getDateFormat().parse(textDate));
34         } catch (ParseException e) {
35             e.printStackTrace();
36         }
37     }
38 
39     @Override
40     public void format(Date date) {
41         System.out.println(getDateFormat().format(date));
42     }
43 }

创建一个ThreadLocal类变量,这里创建时用了一个匿名类,覆盖了initialValue方法,主要作用是创建时初始化实例。

         也可以采用下面方式创建。

 

 1 package com.bijian.study.date;
 2 
 3 import java.text.DateFormat;
 4 import java.text.ParseException;
 5 import java.text.SimpleDateFormat;
 6 import java.util.Date;
 7 
 8 public class DateUtil05 implements DateUtilInterface {
 9 
10     private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
11     
12     @SuppressWarnings("rawtypes")
13     private static ThreadLocal threadLocal = new ThreadLocal() {
14         protected synchronized Object initialValue() {
15             return new SimpleDateFormat(DATE_FORMAT);
16         }
17     };
18 
19     public DateFormat getDateFormat() {
20         return (DateFormat) threadLocal.get();
21     }
22 
23     @Override
24     public void parse(String textDate) {
25 
26         try {
27             System.out.println(getDateFormat().parse(textDate));
28         } catch (ParseException e) {
29             e.printStackTrace();
30         }
31     }
32 
33     @Override
34     public void format(Date date) {
35         System.out.println(getDateFormat().format(date));
36     }
37 }

修改DateMainTest.java的DateUtilInterface dateUtil = new DateUtil03();为DateUtilInterface dateUtil = new DateUtil04();或者DateUtilInterface dateUtil = new DateUtil05();测试OK。

 

      最后,当然也可以使用apache commons-lang包的DateFormatUtils或者FastDateFormat实现,apache保证是线程安全的,并且更高效。

 

     附:Oracle官方bug说明: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6178997

 

  转自 http://bijian1013.iteye.com/blog/1873336

 

 

 

SimpleDateFormat线程不安全(转)

标签:style   blog   http   io   color   ar   使用   java   for   

原文地址:http://www.cnblogs.com/SamuelSun/p/4064256.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!