根据javadocs描述,DateFormat类是非线程安全的。通过多线程并发测试,也证实了这一点。
通过此次测试得出的一些经验:
- 经多线程并发UT验证,DateFormat的format一直都正确运行(基于StringBuffer实现),但parse经常出问题(未使用任何并发技术)
- 即使DateFormat的parse运行正常结束,最终结果也可能不对!
- DateFormatThreadLocal、DateTimeFormatterWrapper与FastDateFormatWrapper都正确运行
- 通过500并发量+5个线程的性能测试来看,对于format操作,DateTimeFormatterWrapper 最优,FastDateFormatWrapper 次之,DateFormatThreadLocal 最差;对于parse操作,三者差距微乎其微
/** * 可格式化的日期接口定义。 * * @author Bert Lee * @version 2014-8-16 */ public interface DateFormattable { /** * 默认日期格式 */ String PATTERN = "yyyy-MM-dd"; /** * Formats a Date into a date/time string. * * @param date * @return * @see java.text.DateFormat#format(Date) */ String format(Date date); /** * Parses text from the beginning of the given string to produce a date. * * @param source * @return * @throws ParseException * @see java.text.DateFormat#parse(String) */ Date parse(String source) throws ParseException; }
/** * {@link DateFormat} wrapper. * * @author Bert Lee * @version 2014-8-16 */ public class DateFormatWrapper implements DateFormattable { private final DateFormat format; public DateFormatWrapper() { this(PATTERN); } public DateFormatWrapper(String pattern) { this.format = new SimpleDateFormat(pattern); } /** * <font color="red">经多线程UT验证,format都正确运行(基于StringBuffer实现)!</font> */ @Override public String format(Date date) { return this.format.format(date); } /** * <font color="red">经多线程UT验证,parse经常出问题(未使用任何并发技术)!</font> */ @Override public Date parse(String source) throws ParseException { return this.format.parse(source); } }
/** * Date parse task. * * @author Bert Lee * @version 2014-8-16 */ public class DateParseCallable implements Callable<Date> { private DateFormattable formatter; private String source; public DateParseCallable(DateFormattable formatter, String source) { this.formatter = formatter; this.source = source; } @Override public Date call() throws Exception { return this.formatter.parse(source); } }
/** * Concurrent thread {@link java.util.concurrent.Executor Executor} wrapper. * * @author Bert Lee * @version 2014-8-16 */ public class ConcurrentThreadExecutorWrapper<T> { private ExecutorService executor; private Callable<T> task; private List<Future<T>> results; private TestScale runTimes; public ConcurrentThreadExecutorWrapper(Callable<T> task) { this(task, TestScale.BASIC); } public ConcurrentThreadExecutorWrapper(Callable<T> task, TestScale runTimes) { // pool with 5 threads this.executor = Executors.newFixedThreadPool(5); this.task = task; this.runTimes = runTimes; } public void run() { results = new ArrayList<Future<T>>(); // perform 10 times date conversions for (int i = 0; i < runTimes.getValue(); i++) { results.add(executor.submit(task)); } executor.shutdown(); } public void printResults() throws Exception { this.run(); // look at the results for (Future<T> result : results) { out.println(result.get()); } } }
/** * Test for {@link ConcurrentThreadExecutorWrapper}. * <p> * 参考并优化实现了<a href="http://stackoverflow.com/questions/4021151/java-dateformat-is-not-threadsafe-what-does-this-leads-to"> * “Java DateFormat is not thread-safe” what does this leads to?</a> * * @author Bert Lee * @version 2014-8-16 */ public class DateFormatExecutorTest { // 日期转换格式 private static final String pattern = "yyyy-MM-dd HH:mm"; /* * 经多线程UT验证,DateFormat的format一直都正确运行(基于StringBuffer实现),但parse经常出问题(未使用任何并发技术)! * 即使DateFormat的parse运行正常结束,最终结果也可能不对! * * DateFormatThreadLocal、DateTimeFormatterWrapper与FastDateFormatWrapper都正确运行。 */ @Test(dataProvider = "parse", groups = "parse") public void parse(DateFormattable formatter, String source) throws Exception { Callable<Date> task = new DateParseCallable(formatter, source); ConcurrentThreadExecutorWrapper<Date> executor = new ConcurrentThreadExecutorWrapper<Date>(task); out.println(formatter.getClass().getSimpleName() + " parse result:"); executor.printResults(); } @DataProvider(name = "parse") protected static final Object[][] parseTestData() { Object[][] testData = new Object[][] { // { new DateFormatWrapper(pattern), "2014-08-16 08:23:07" }, // 经常报错,即使运行结束,最终结果也可能不对! { new DateFormatThreadLocal(pattern), "2014-08-16 08:23:07" }, { new DateTimeFormatterWrapper(pattern), "2014-08-16 08:23" }, { new FastDateFormatWrapper(pattern), "2014-08-16 08:23:07" }, }; return testData; } @Test(dataProvider = "format", groups = "format") public void format(DateFormattable formatter) throws Exception { Date date = new Date(); Callable<String> task = new DateFormatCallable(formatter, date); ConcurrentThreadExecutorWrapper<String> executor = new ConcurrentThreadExecutorWrapper<String>(task); out.println(formatter.getClass().getSimpleName() + " format result:"); executor.printResults(); } @DataProvider(name = "format") protected static final Object[][] formatTestData() { Object[][] testData = new Object[][] { { new DateFormatWrapper(pattern) }, { new DateFormatThreadLocal(pattern) }, { new DateTimeFormatterWrapper(pattern) }, { new FastDateFormatWrapper(pattern) }, }; return testData; } }
相关推荐
《Java并发编程实战》是Java开发者深入理解和掌握并发编程的一本经典著作。这本书全面地介绍了如何在Java平台上高效、安全地编写多线程程序,帮助读者理解并解决并发编程中的各种挑战。 首先,我们需要理解“并发”...
Java在并发环境中SimpleDateFormat多种解决方案 Java在并发环境中使用SimpleDateFormat时,可能会遇到线程安全问题。下面将介绍六种解决方案来解决这个问题。 方法一:使用局部变量 在需要执行格式化的地方都新建...
7. **java.concurrent**: 并发编程包,包含线程(Thread)、线程池(ExecutorService)和并发工具类(如Semaphore、CyclicBarrier),帮助开发者编写多线程应用。 8. **java.sql**: 提供了与关系数据库交互的接口,...
在Java编程语言中,`DateFormat`类是处理日期和时间格式化的重要工具,但它的线程安全性是一个常见的问题。在多线程环境下,不恰当的使用`DateFormat`可能导致数据不一致、性能下降甚至程序崩溃。这篇博客将深入探讨...
java.text.DateFormat cal = java.text.DateFormat.getDateTimeInstance(); System.out.println(cal.format(new java.util.Date()) + "-" + url + "" + sock.getInetAddress() + "<BR>"); return host; } // ...
根据Java官方文档的建议,每个线程应该拥有自己独立的日期格式实例,或者在访问`DateFormat`时进行适当的同步控制,以避免并发问题。 首先,我们来看一个简单的例子,展示`DateFormat`非线程安全的问题。在给定的...
`java.text` 包中的 `NumberFormat` 和 `DateFormat` 用于格式化数字和日期,`ResourceBundle` 用于管理不同语言的文本资源。 10. **安全性** Java 1.6 引入了安全管理器(Security Manager),用于控制程序的访问...
8. **国际化与本地化**:java.text和java.util包提供了对国际化和本地化的支持,如NumberFormat和DateFormat类用于格式化数字和日期,ResourceBundle用于根据地区加载不同的资源。 9. **Java标准库**:包括诸如Math...
10. **java.concurrent**:多线程和并发处理相关类,如Thread、ExecutorService和Semaphore,支持高级并发控制和并行计算。 11. **javax.xml**:处理XML文档的解析、生成和验证,如DOM、SAX和StAX API。 12. **...
7. **java.util.concurrent**: 并发工具包,提供了线程池、并发容器(如ConcurrentHashMap)、锁机制(如ReentrantLock)以及其他并发工具类,为多线程编程提供了强大支持。 8. **java.net**: 网络编程相关类,如...
8. **java.concurrent**:多线程处理的包,包含Thread、ExecutorService、Semaphore等类,方便实现并发编程。 9. **java.text**:处理文本格式化,如数字、日期、货币等,包含NumberFormat和DateFormat类。 10. **...
在Java编程语言中,实现多国时间显示的功能主要涉及到日期和时间处理,国际化(i18n)以及线程管理...对于初学者来说,这样的项目不仅能够锻炼编程技能,还能深入理解Java中的并发编程、GUI设计以及国际化的实现方式。
7. **java.text**:处理文本格式化和解析,如DateFormat、NumberFormat、MessageFormat等。 8. **java.concurrent**:多线程和并发编程包,包括Thread、ExecutorService、Future、Semaphore等工具类。 9. **java....
10. **java.concurrent**:并发和多线程处理包,包括Thread、ExecutorService、Semaphore等,有助于在多核环境下提高程序性能。 11. **java.lang.reflect**:反射机制,允许程序在运行时检查和修改自身行为,实现...
8. **国际化**:java.text和java.util包提供了支持多语言环境的工具,如DateFormat、NumberFormat和MessageFormat,便于处理日期、数字和消息的格式化。 9. **XML处理**:Java2类库包含了DOM(Document Object ...
5. **多线程**:Java通过`java.lang.Thread`和`java.util.concurrent`包提供多线程编程的支持,可以创建和管理线程,实现并发和同步。 6. **反射**:`java.lang.reflect`包允许程序在运行时检查和修改类、接口、...
4. **多线程**:Java提供了Thread类和Runnable接口来实现并发执行。synchronized关键字用于同步访问共享资源,wait()、notify()和notifyAll()方法用于线程间通信。 5. **I/O流**:Java的I/O流体系结构包括字节流...
JAVA提供了Socket和ServerSocket类实现TCP/IP通信,DatagramSocket和DatagramPacket处理UDP通信。网络编程还涉及到IP、端口、URL的概念。 第十一章 **JAVA多媒体编程** JAVA支持多媒体处理,如字体、颜色、图形...