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