ice world

          There is nothing too difficult if you put your heart into it.
          posts - 104, comments - 103, trackbacks - 0, articles - 0

          【轉】ThreadLocal 解決SimpleDateFormat非線程安全

          Posted on 2011-04-16 02:34 IceWee 閱讀(1057) 評論(0)  編輯  收藏 所屬分類: Java
          大致意思:Tim Cull碰到一個SimpleDateFormat帶來的嚴重的性能問題,該問題主要有SimpleDateFormat引發,創建一個 SimpleDateFormat實例的開銷比較昂貴,解析字符串時間時頻繁創建生命周期短暫的實例導致性能低下。即使將 SimpleDateFormat定義為靜態類變量,貌似能解決這個問題,但是SimpleDateFormat是非線程安全的,同樣存在問題,如果用 ‘synchronized’線程同步同樣面臨問題,同步導致性能下降(線程之間序列化的獲取SimpleDateFormat實例)。

          Tim Cull使用Threadlocal解決了此問題,對于每個線程SimpleDateFormat不存在影響他們之間協作的狀態,為每個線程創建一個SimpleDateFormat變量的拷貝或者叫做副本,代碼如下:

           

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

          /** 
           * 使用ThreadLocal以空間換時間解決SimpleDateFormat線程安全問題。 
           
          */

          public class DateUtil {
              
          private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
              @SuppressWarnings(
          "rawtypes")
              
          private static ThreadLocal threadLocal = new ThreadLocal() {
                  
          protected synchronized Object initialValue() {
                      
          return new SimpleDateFormat(DATE_FORMAT);
                  }

              }
          ;

              
          public static DateFormat getDateFormat() {
                  
          return (DateFormat) threadLocal.get();
              }


              
          public static Date parse(String textDate) throws ParseException {
                  
          return getDateFormat().parse(textDate);
              }

          }


          創建一個ThreadLocal類變量,這里創建時用了一個匿名類,覆蓋了initialValue方法,主要作用是創建時初始化實例。也可以采用下面方式創建;

          import java.text.DateFormat;
          import java.text.SimpleDateFormat;

          /** 
           * 使用ThreadLocal以空間換時間解決SimpleDateFormat線程安全問題
           
          */

          public class DateUtil {    
              
          private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
              
          private static ThreadLocal threadLocal = new ThreadLocal();
              
          // 第一次調用get將返回null
              
          // 獲取線程的變量副本,如果不覆蓋initialValue,第一次get返回null,
              
          // 故需要初始化一個SimpleDateFormat,并set到threadLocal中
              public static DateFormat getDateFormat() {
                  DateFormat df 
          = (DateFormat) threadLocal.get();
                  
          if (df == null{
                      df 
          = new SimpleDateFormat(DATE_FORMAT);  
                      threadLocal.set(df);
                  }

                  
          return df;
              }

          }



          我們看下我們覆蓋的initialValue方法:

          protected T initialValue() {
              
          return null;    // 直接返回null
          }



          當然也可以使用:
          apache commons-lang包的DateFormatUtils或者FastDateFormat實現,apache保證是線程安全的,并且更高效。

          主站蜘蛛池模板: 都江堰市| 扎囊县| 裕民县| 博白县| 怀集县| 禹州市| 明水县| 桑日县| 合作市| 永康市| 沂南县| 昔阳县| 仙游县| 淮南市| 中方县| 虞城县| 启东市| 兰溪市| 龙游县| 伊宁市| 云龙县| 上蔡县| 承德市| 潞西市| 无为县| 时尚| 西昌市| 肇州县| 唐山市| 济宁市| 密山市| 鹿邑县| 弥勒县| 盘锦市| 望城县| 玉林市| 怀化市| 绵竹市| 荔浦县| 合川市| 曲靖市|