Java多線程編程中使用DateFormat類(lèi)
DateFormat 類(lèi)是一個(gè)非線程安全的類(lèi)。javadocs 文檔里面提到"Date formats是不能同步的。 我們建議為每個(gè)線程創(chuàng)建獨(dú)立的日期格式。 如果多個(gè)線程同時(shí)訪問(wèn)一個(gè)日期格式,這需要在外部加上同步代碼塊。"
以下的代碼為我們展示了如何在一個(gè)線程環(huán)境里面使用DateFormat把字符串日期轉(zhuǎn)換為日期對(duì)象。創(chuàng)建一個(gè)實(shí)例來(lái)獲取日期格式會(huì)比較高效,因?yàn)橄到y(tǒng)不需要多次獲取本地語(yǔ)言和國(guó)家。
public class DateFormatTest { private final DateFormat format = new SimpleDateFormat("yyyyMMdd"); public Date convert(String source) throws ParseException{ Date d = format.parse(source); return d; } }
這段代碼是非線程安全的。我們可以通過(guò)在多個(gè)線程中調(diào)用它。在以下調(diào)用的代碼中,我創(chuàng)建了一個(gè)有兩個(gè)線程的線程池,并提交了5個(gè)日期轉(zhuǎn)換任務(wù),之后查看運(yùn)行結(jié)果:
final DateFormatTest t =new DateFormatTest(); Callable<Date> task =new Callable<Date>(){ public Date call()throws Exception { return t.convert("20100811"); } }; //讓我們嘗試2個(gè)線程的情況 ExecutorService exec = Executors.newFixedThreadPool(2); List<Future<Date>> results = new ArrayList<Future<Date>>(); //實(shí)現(xiàn)5次日期轉(zhuǎn)換 for(int i =0; i <5; i++){ results.add(exec.submit(task)); } exec.shutdown(); //查看結(jié)果 for(Future<Date> result : results){ System.out.println(result.get()); }
代碼的運(yùn)行結(jié)果并非如我們所愿 - 有時(shí)候,它輸出正確的日期,有時(shí)候會(huì)輸出錯(cuò)誤的(例如.Sat Jul 31 00:00:00 BST 2012),有些時(shí)候甚至?xí)伋鯪umberFormatException!
如何并發(fā)使用DateFormat類(lèi)
我們可以有多種方法在線程安全的情況下使用DateFormat類(lèi)。
1. 同步
最簡(jiǎn)單的方法就是在做日期轉(zhuǎn)換之前,為DateFormat對(duì)象加鎖。這種方法使得一次只能讓一個(gè)線程訪問(wèn)DateFormat對(duì)象,而其他線程只能等待。
public Date convert(String source) throws ParseException{ synchronized(format) { Date d = format.parse(source); return d; } }
2. 使用ThreadLocal
另外一個(gè)方法就是使用ThreadLocal變量去容納DateFormat對(duì)象,也就是說(shuō)每個(gè)線程都有一個(gè)屬于自己的副本,并無(wú)需等待其他線程去釋放它。這種方法會(huì)比使用同步塊更高效。
public class DateFormatTest { private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){ @Override protected DateFormat initialValue() { return new SimpleDateFormat("yyyyMMdd"); } }; public Date convert(String source) throws ParseException{ Date d = df.get().parse(source); return d; } }
3. Joda-Time
Joda-Time 是一個(gè)很棒的開(kāi)源的 JDK 的日期和日歷 API 的替代品,其 DateTimeFormat 是線程安全而且不變的。
import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import java.util.Date; public class DateFormatTest { private final DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd"); public Date convert(String source){ DateTime d = fmt.parseDateTime(source); returnd.toDate(); } }
相關(guān)文章
運(yùn)用Spring?Aop+注解實(shí)現(xiàn)日志記錄
我們都知道Spring框架的兩大特性分別是 IOC (控制反轉(zhuǎn))和 AOP (面向切面),這個(gè)是每一個(gè)Spring學(xué)習(xí)視頻里面一開(kāi)始都會(huì)提到的,這里,如果我們使用Aop來(lái)記錄日志,那是再好不過(guò)了,感興趣的朋友跟隨小編一起學(xué)習(xí)下Spring?Aop注解實(shí)現(xiàn)日志記錄的過(guò)程吧2022-01-01Java Mybatis架構(gòu)設(shè)計(jì)深入了解
在本篇文章里小編給大家整理的是一篇關(guān)于Java Mybatis架構(gòu)設(shè)計(jì)詳解內(nèi)容,對(duì)此有興趣的朋友們可以參考下,希望能夠給你帶來(lái)幫助2021-11-11Java設(shè)計(jì)模式之工廠模式實(shí)現(xiàn)方法詳解
這篇文章主要介紹了Java設(shè)計(jì)模式之工廠模式實(shí)現(xiàn)方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了工廠模式的分類(lèi)、原理、實(shí)現(xiàn)方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-12-12Spring boot詳解緩存redis實(shí)現(xiàn)定時(shí)過(guò)期方法
本篇文章分享的就是spring boot中的一個(gè)輪子,spring cache注解的方式實(shí)現(xiàn)接口數(shù)據(jù)緩存。默認(rèn)的配置想非常簡(jiǎn)單,但是有一個(gè)弊端是緩存數(shù)據(jù)為永久緩存,本次將介紹如何設(shè)置接口緩存數(shù)據(jù)的過(guò)期時(shí)間2022-07-07SpringBoot創(chuàng)建Docker鏡像的方法步驟
這篇文章主要介紹了SpringBoot創(chuàng)建Docker鏡像的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11java ArrayBlockingQueue阻塞隊(duì)列的實(shí)現(xiàn)示例
ArrayBlockingQueue是一個(gè)基于數(shù)組實(shí)現(xiàn)的阻塞隊(duì)列,本文就來(lái)介紹一下java ArrayBlockingQueue阻塞隊(duì)列的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02詳解JAVAEE——SSH三大框架整合(spring+struts2+hibernate)
這篇文章主要介紹了詳解JAVAEE——SSH三大框架整合(spring+struts2+hibernate),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07Mybatis plus 配置多數(shù)據(jù)源的實(shí)現(xiàn)示例
這篇文章主要介紹了Mybatis plus 配置多數(shù)據(jù)源的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08