java的SimpleDateFormat線程不安全出問題了,項(xiàng)目不支持java8,虛竹教你這一招

      網(wǎng)友投稿 803 2025-04-02

      目錄

      一、場景

      二、SimpledateFormat線程為什么是線程不安全的呢?

      驗(yàn)證SimpledateFormat線程不安全

      三、FastDateFormat源碼分析

      實(shí)踐

      四、結(jié)論

      一、場景

      Java8以前,要格式化日期時(shí)間,就需要用到SimpleDateFormat。

      但我們知道SimpleDateFormat是線程不安全的,處理時(shí)要特別小心,要加鎖或者不能定義為static,要在方法內(nèi)new出對象,再進(jìn)行格式化。很麻煩,而且重復(fù)地new出對象,也加大了內(nèi)存開銷。

      后來Apache 在commons-lang 包中擴(kuò)展了FastDateFormat對象,它是一個(gè)線程安全的,可以用來完美替換SimpleDateFormat。

      二、SimpleDateFormat線程為什么是線程不安全的呢?

      來看看SimpleDateFormat的源碼

      // Called from Format after creating a FieldDelegate private StringBuffer format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) { // Convert input date to time field list calendar.setTime(date); ... }

      1

      2

      3

      java的SimpleDateFormat線程不安全出問題了,項(xiàng)目不支持java8,虛竹教你這一招

      4

      5

      6

      7

      問題就出在成員變量calendar,如果在使用SimpleDateFormat時(shí),用static定義,那SimpleDateFormat變成了共享變量。那SimpleDateFormat中的calendar就可以被多個(gè)線程訪問到。

      驗(yàn)證SimpleDateFormat線程不安全

      public class SimpleDateFormatDemoTest { private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) { //1、創(chuàng)建線程池 ExecutorService pool = Executors.newFixedThreadPool(5); //2、為線程池分配任務(wù) ThreadPoolTest threadPoolTest = new ThreadPoolTest(); for (int i = 0; i < 10; i++) { pool.submit(threadPoolTest); } //3、關(guān)閉線程池 pool.shutdown(); } static class ThreadPoolTest implements Runnable{ private volatile int i=0; @Override public void run() { while (i<10){ String dateString = simpleDateFormat.format(new Date()); try { Date parseDate = simpleDateFormat.parse(dateString); String dateString2 = simpleDateFormat.format(parseDate); System.out.println(Thread.currentThread().getName()+" : "+i++); System.out.println(dateString.equals(dateString2)); System.out.println("-------------------------"); } catch (ParseException e) { e.printStackTrace(); } } } } }

      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

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      出現(xiàn)了兩次false,說明線程是不安全的。

      三、FastDateFormat源碼分析

      Apache Commons Lang 3.5

      1

      //FastDateFormat @Override public String format(final Date date) { return printer.format(date); } @Override public String format(final Date date) { final Calendar c = Calendar.getInstance(timeZone, locale); c.setTime(date); return applyRulesToString(c); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      源碼中 Calender 是在 format 方法里創(chuàng)建的,肯定不會出現(xiàn) setTime 的線程安全問題。這樣線程安全疑惑解決了。那還有性能問題要考慮?

      我們來看下FastDateFormat是怎么獲取的

      FastDateFormat.getInstance(); FastDateFormat.getInstance(CHINESE_DATE_TIME_PATTERN);

      1

      2

      看下對應(yīng)的源碼

      /** * 獲得 FastDateFormat實(shí)例,使用默認(rèn)格式和地區(qū) * * @return FastDateFormat */ public static FastDateFormat getInstance() { return CACHE.getInstance(); } /** * 獲得 FastDateFormat 實(shí)例,使用默認(rèn)地區(qū)
      * 支持緩存 * * @param pattern 使用{@link Java.text.SimpleDateFormat} 相同的日期格式 * @return FastDateFormat * @throws IllegalArgumentException 日期格式問題 */ public static FastDateFormat getInstance(final String pattern) { return CACHE.getInstance(pattern, null, null); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      這里有用到一個(gè)CACHE,看來用了緩存,往下看

      private static final FormatCache CACHE = new FormatCache(){ @Override protected FastDateFormat createInstance(final String pattern, final TimeZone timeZone, final Locale locale) { return new FastDateFormat(pattern, timeZone, locale); } }; // abstract class FormatCache { ... private final ConcurrentMap cInstanceCache = new ConcurrentHashMap<>(7); private static final ConcurrentMap C_DATE_TIME_INSTANCE_CACHE = new ConcurrentHashMap<>(7); ... }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      在getInstance 方法中加了ConcurrentMap 做緩存,提高了性能。且我們知道ConcurrentMap 也是線程安全的。

      實(shí)踐

      /** * 年月格式 {@link FastDateFormat}:yyyy-MM */ public static final FastDateFormat NORM_MONTH_FORMAT = FastDateFormat.getInstance(NORM_MONTH_PATTERN);

      1

      2

      3

      4

      //FastDateFormatpublic static FastDateFormat getInstance(final String pattern) { return CACHE.getInstance(pattern, null, null);}

      1

      如圖可證,是使用了ConcurrentMap 做緩存。且key值是格式,時(shí)區(qū)和locale(語境)三者都相同為相同的key。

      四、結(jié)論

      java8之前,可使用FastDateFormat 替換SimpleDateFormat,達(dá)到線程安全的目的;

      java8及以上的,java8提供了一套新的日期時(shí)間API,可以使用DateTimeFormatter來代替SimpleDateFormat。具體的源碼分析,可以看這里,傳送門:萬字博文教你搞懂java源碼的日期和時(shí)間相關(guān)用法

      Java 任務(wù)調(diào)度

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:包含連鎖超市管理系統(tǒng)的詞條
      下一篇:excel表加了后綴,想復(fù)制到另外一個(gè)表格后綴不見了(excel復(fù)制表格格式不變到另外一個(gè)表格)
      相關(guān)文章
      亚洲av无一区二区三区| 亚洲欧美日本韩国| 免费在线观看亚洲| 亚洲爆乳无码精品AAA片蜜桃| 77777亚洲午夜久久多喷| 亚洲伊人久久大香线焦| 亚洲精品视频专区| 亚洲精品国产成人99久久| 亚洲电影国产一区| 久久久久久亚洲Av无码精品专口 | 国产亚洲精品国产| 亚洲精品无码av人在线观看 | 精品亚洲成α人无码成α在线观看| 亚洲AⅤ永久无码精品AA | 亚洲Aⅴ无码一区二区二三区软件 亚洲AⅤ视频一区二区三区 | 日本亚洲免费无线码| 亚洲综合色婷婷在线观看| 国产成人亚洲综合一区| 亚洲日韩国产二区无码| 亚洲国产AV一区二区三区四区 | 久久久久亚洲AV无码专区首| 久久亚洲精品AB无码播放| 亚洲AV无码久久精品成人| 老司机亚洲精品影院| 亚洲精品视频久久| 亚洲人成www在线播放| 亚洲欧美第一成人网站7777| 亚洲AV无码资源在线观看| 亚洲国产成人a精品不卡在线| 亚洲乱码中文字幕手机在线 | 亚洲三级在线观看| 亚洲国产av玩弄放荡人妇| 亚洲精品视频免费| 丝袜熟女国偷自产中文字幕亚洲| 日韩亚洲变态另类中文| 亚洲无线码一区二区三区| 亚洲成熟xxxxx电影| 亚洲图片中文字幕| 亚洲欧美熟妇综合久久久久| 亚洲成av人片一区二区三区| 激情97综合亚洲色婷婷五 |