Java在并發(fā)環(huán)境中SimpleDateFormat多種解決方案
先來(lái)看一個(gè)多線程下使用例子,看到運(yùn)行結(jié)果會(huì)出現(xiàn)異常:
import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors; public class SimpleDateFormateTest { public static void main(String[] args) { final DateFormat df = new SimpleDateFormat('yyyyMMdd,HHmmss'); ExecutorService ts = Executors.newFixedThreadPool(100); for (;;) { ts.execute(new Runnable() { @Overridepublic void run() { try { //生成隨機(jī)數(shù),格式化日期 String format = df.format(new Date(Math.abs(new Random().nextLong()))); System.out.println(format); } catch (Exception e) { e.printStackTrace(); System.exit(1); }} }); } } }
運(yùn)行結(jié)果:

在并發(fā)環(huán)境下使用SimpleDateFormat,正常的打開(kāi)放式如下:
為了能夠在多線程環(huán)境下使用SimpleDateFormat,有這六種方法:
方法一
在需要執(zhí)行格式化的地方都新建SimpleDateFormat實(shí)例,使用局部變量來(lái)存放SimpleDateFormat實(shí)例
public static String formatDate(Date date)throws ParseException{ SimpleDateFormat sdf = new SimpleDateFormat('yyyy-MM-dd HH:mm:ss'); return sdf.format(date);}
這種方法可能會(huì)導(dǎo)致短期內(nèi)創(chuàng)建大量的SimpleDateFormat實(shí)例,如解析一個(gè)excel表格里的字符串日期。
方法二
為了避免創(chuàng)建大量的SimpleDateFormat實(shí)例,往往會(huì)考慮把SimpleDateFormat實(shí)例設(shè)為靜態(tài)成員變量,共享SimpleDateFormat對(duì)象。這種情況下就得對(duì)SimpleDateFormat添加同步。
private static SimpleDateFormat sdf = new SimpleDateFormat('yyyy-MM-dd HH:mm:ss');public static String formatDate(Date date)throws ParseException{ synchronized(sdf){ return sdf.format(date); } }
這種方法的缺點(diǎn)也很明顯,就是在高并發(fā)的環(huán)境下會(huì)導(dǎo)致解析被阻塞。
方法三
方法加同步鎖synchronized,在同一時(shí)刻,只有一個(gè)線程可以執(zhí)行類中的某個(gè)方法。
缺點(diǎn):性能較差,每次都要等待鎖釋放后其他線程才能進(jìn)入。
方案四 使用第三方包
這個(gè)我有嘗試cn.hutool和common-lang3提供的FastDateFormat最后的結(jié)果其實(shí)并不滿意,因?yàn)檫@兩個(gè)包都沒(méi)能幫助我檢查非正常時(shí)間,比如2018-07-32這種日期也被認(rèn)為是正確的時(shí)期格式了
方法五(推薦)
要在高并發(fā)環(huán)境下能有比較好的體驗(yàn),可以使用ThreadLocal來(lái)限制SimpleDateFormat只能在線程內(nèi)共享,這樣就避免了多線程導(dǎo)致的線程安全問(wèn)題。
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { return new SimpleDateFormat('yyyy-MM-dd HH:mm:ss'); }};public static String format(Date date) { return threadLocal.get().format(date);}
方案六 DateTimeFormatter使用
Java8提供了新的日期時(shí)間API,其中包括用于日期時(shí)間格式化的DateTimeFormatter,它與SimpleDateFormat的有什么區(qū)別呢?
問(wèn)題解決
兩者最大的區(qū)別是,Java8的DateTimeFormatter也是線程安全的,而SimpleDateFormat并不是線程安全。
解析日期
String dateStr= '2016年10月25日'; DateTimeFormatter formatter = DateTimeFormatter.ofPattern('yyyy年MM月dd日'); LocalDate date= LocalDate.parse(dateStr, formatter);
日期轉(zhuǎn)換為字符串
LocalDateTime now = LocalDateTime.now(); DateTimeFormatter format = DateTimeFormatter.ofPattern('yyyy年MM月dd日 hh:mm a'); String nowStr = now .format(format);
由DateTimeFormatter的靜態(tài)方法ofPattern()構(gòu)建日期格式,LocalDateTime和LocalDate等一些表示日期或時(shí)間的類使用parse和format方法把日期和字符串做轉(zhuǎn)換。
使用新的API,整個(gè)轉(zhuǎn)換過(guò)程都不需要考慮線程安全的問(wèn)題。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. ASP動(dòng)態(tài)網(wǎng)頁(yè)制作技術(shù)經(jīng)驗(yàn)分享2. XML解析錯(cuò)誤:未組織好 的解決辦法3. 解析原生JS getComputedStyle4. 小技巧處理div內(nèi)容溢出5. 得到XML文檔大小的方法6. CSS可以做的幾個(gè)令你嘆為觀止的實(shí)例分享7. php使用正則驗(yàn)證密碼字段的復(fù)雜強(qiáng)度原理詳細(xì)講解 原創(chuàng)8. 詳解瀏覽器的緩存機(jī)制9. 淺談?dòng)蓀osition屬性引申的css進(jìn)階討論10. ASP中實(shí)現(xiàn)字符部位類似.NET里String對(duì)象的PadLeft和PadRight函數(shù)

網(wǎng)公網(wǎng)安備