日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于SimpleDateFormat线程不安全的源码分析

發布時間:2024/7/23 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于SimpleDateFormat线程不安全的源码分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

SimpleDateFormat,線程不安全,源碼分析

1、先看SimpleDateFormat類圖

SimpleDateFormat繼承了DateFormat
DateFormat中有個成員變量是Calendar,這個先記住,線程不安全主要就是因為這個成員變量

2、看下圖SimpleDateFormat的parse方法

這個方法,主要就兩步,
第一步是針對入參text做了一系列操作,這里可以省略不看
第二步就是下圖代碼中的紅框部分:calb.establish(calendar),這個入參就是上面說的
SimpleDateFormat的常成員變量

3、看下圖,calb.establish(calendar)方法的實現

圖中的三步,都不是線程安全的,因為入參cal是SimpleDateFormat的成員變量
當多個線程同時操作一個SimpleDateFormat的時候,SimpleDateFormat中的Calendar屬性也就會被多個線程拿到,那么下面這三步就可能因為多個線程同時執行而亂掉

具體測試代碼

我們用多個線程,同時操作SimpleDateFormat的parse方法,如果把SimpleDateFormat放在成員變量上,就會大概率報錯,因為此時SimpleDateFormat會被多個線程同時使用。
解決方法有很多,最常見的就是在每次用SimpleDateFormat的時候都重新new一個。

import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class MainTest {private static ExecutorService executor = Executors.newCachedThreadPool();// 定義SimpleDateFormat為成員變量,不安全private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 使用成員變量轉換,線程不安全public static String unSafeFormatDate(Date date) throws ParseException {return sdf.format(date);}// 使用成員變量轉換,線程不安全public static Date unSafeParse(String strDate) throws ParseException {return sdf.parse(strDate);}// 每次轉換都創建一個SimpleDateFormat,線程安全public static String safeFormatDate(Date date) throws ParseException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sdf.format(date);}// 每次轉換都創建一個SimpleDateFormat,線程安全public static Date safeParse(String strDate) throws ParseException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sdf.parse(strDate);}public static void main(String[] args) {for (int i = 0; i < 5; i++) {executor.execute(new Runnable() {@Overridepublic void run() {try {Date date = new Date(); // System.out.println(Thread.currentThread().getName() + ":" + unSafeFormatDate(date));System.out.println(Thread.currentThread().getName() + ":" + unSafeParse("2020-02-02 02:02:02"));} catch (ParseException e) {e.printStackTrace();}}});}} }

由于線程不安全,常見的錯誤如下:

Exception in thread "pool-1-thread-3" Exception in thread "pool-1-thread-1" java.lang.NumberFormatException: multiple pointsat sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1890)at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)at java.lang.Double.parseDouble(Double.java:538)at java.text.DigitList.getDouble(DigitList.java:169)at java.text.DecimalFormat.parse(DecimalFormat.java:2089)at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869)at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)at java.text.DateFormat.parse(DateFormat.java:364)at com.zs.qunfx.simpleDateFormat.MainTest.unSafeParse(MainTest.java:27)at com.zs.qunfx.simpleDateFormat.MainTest$1.run(MainTest.java:51)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748) Exception in thread "pool-1-thread-8" java.lang.NumberFormatException: For input string: ""at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)at java.lang.Long.parseLong(Long.java:601)at java.lang.Long.parseLong(Long.java:631)at java.text.DigitList.getLong(DigitList.java:195)at java.text.DecimalFormat.parse(DecimalFormat.java:2084)at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)at java.text.DateFormat.parse(DateFormat.java:364)at com.zs.qunfx.simpleDateFormat.MainTest.unSafeParse(MainTest.java:27)at com.zs.qunfx.simpleDateFormat.MainTest$1.run(MainTest.java:51)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)

總結

以上是生活随笔為你收集整理的关于SimpleDateFormat线程不安全的源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。