SimpleDateFormat与线程安全
SimpleDateFormat不是線程安全的。
SimpleDateFormat(下面簡(jiǎn)稱sdf)類內(nèi)部有一個(gè)Calendar對(duì)象引用,它用來儲(chǔ)存和這個(gè)sdf相關(guān)的日期信息,例如sdf.parse(dateStr),sdf.format(date) 諸如此類的方法參數(shù)傳入的日期相關(guān)String, Date等等, 都是交由Calendar引用來存儲(chǔ)的。這樣就會(huì)導(dǎo)致一個(gè)問題,如果多個(gè)線程共享sdf, 也就會(huì)共享這個(gè)Calendar引用, 并且, 觀察 sdf.parse() 方法,你會(huì)發(fā)現(xiàn)有如下的調(diào)用:
Date parse() {calendar.clear(); //1: 清理calendar... //2: 執(zhí)行一些操作, 設(shè)置 calendar 的日期什么的calendar.getTime(); //3: 獲取calendar的時(shí)間}操作1和操作3會(huì)互相影響,并且方法又不是同步方法,所以存在線程安全問題。
如果 線程A 調(diào)用了 sdf.parse(), 并且進(jìn)行了 calendar.clear()后還未執(zhí)行calendar.getTime()的時(shí)候,線程B又調(diào)用了sdf.parse(), 這時(shí)候線程B也執(zhí)行了sdf.clear()方法, 這樣就導(dǎo)致線程A的的calendar數(shù)據(jù)被清空了(實(shí)際上A,B的同時(shí)被清空了).
又或者當(dāng) A 執(zhí)行了calendar.clear() 后被掛起, 這時(shí)候B 開始調(diào)用sdf.parse()并順利i結(jié)束, 這樣 A 的 calendar內(nèi)存儲(chǔ)的的date 變成了后來B設(shè)置的calendar的date
解決方案:
1:每次用到都新建一個(gè)SimpleDateFormat,做到不在線程間共享。
由于SimpleDateFormat創(chuàng)建耗費(fèi)很大,會(huì)涉及到大量的SimpleDateFormat對(duì)象的創(chuàng)建與銷毀操作,所以這種方式性能較差。適合對(duì)性能要求沒那么高的場(chǎng)景。
2:封裝外部方法,使用同步synchronize
這種方式在高并發(fā)場(chǎng)景下,對(duì)性能影響較大。可能會(huì)出現(xiàn)線程長(zhǎng)時(shí)間阻塞的情況。
3:使用ThreadLocal
每個(gè)線程私有SimpleDateFormat對(duì)象,既可以避免線程安全問題,也可以避免方案1的缺點(diǎn)。
4:使用JDK8的最新時(shí)間&日期格式化API
如果你的jdk版本>=1.8,那推薦使用java最新的時(shí)間&日期API,使用DateTimeFormatter,它是線程安全的。
總結(jié)
以上是生活随笔為你收集整理的SimpleDateFormat与线程安全的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 燕麦粥可以减肥吗
- 下一篇: far的比较级和最高级 有两种形式