`

让DateFormat多线程安全

    博客分类:
  • J2EE
阅读更多

"DateFormat 不是同步的。建议为每个线程创建独立的格式实例。如果多个线程同时访问一个格式,则它必须保持外部同步。"----摘自JDK文档中文版 

首先让我们看看一个简单的方法 

public static Date toDate(String dateStr) {
SimpleDateFormat p= new SimpleDateFormat("yyyyMMdd");
try{
    return p.parse(dateStr);
}catch (ParseException e) {
}
return null;
}

 

这个方法是把形如"20110101"这样的字符串转换成Date类型;同时方法是支持多线程并发访问的,但是这个是有代价的,因为每次方法调用都要创建一个SimpleDateFormat 对象。 


很自然的我们就想到以下的改进,将SimpleDateFormat声明为静态全局变量 

 

private static final SimpleDateFormat PATTERN = new SimpleDateFormat("yyyyMMdd");

 

同时为了保证多线程同步访问,方法需要加锁 

 

public synchronied static Date toDate(String dateStr) {
try{
return PATTERN.parse(dateStr);
}catch (ParseException e) {
}
return null;
}

 

这样的优化还是不够的,因为在多线程争用的情况下,性能不佳。最好是每个线程都有自己的DateFormat,这样既不会发生争用,而且对于每个线程都只创建一个DateFormat对象。 
ThreadLocal正好可以满足这种需求。这里不多做解释了,我们一步到位: 

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

public class DateFormatFactory {
	private static final Map<String, ThreadLocal<SimpleDateFormat>> pool = new HashMap<String, ThreadLocal<SimpleDateFormat>>();
	private static final Object lock = new Object();

	public static SimpleDateFormat getDateFormat(String pattern) {
		ThreadLocal<SimpleDateFormat> tl = pool.get(pattern);
		if (tl == null) {
			synchronized (lock) {
				tl = pool.get(pattern);
				if (tl == null) {
					final String p = pattern;
					tl = new ThreadLocal<SimpleDateFormat>() {
						protected synchronized SimpleDateFormat initialValue() {
							return new SimpleDateFormat(p);
						}
					};
					pool.put(p, tl);
				}
			}
		}
		return tl.get();
	}
}

public static Date toDate(String dateStr,String pattern) {
try{
return getDateFormat(pattern).parse(dateStr);
}catch (ParseException e) {
}
return null;
}

 

上面还增加了对不同Pattern的ThreadLocal的缓存,这样对于每一个线程每一种pattern都只要创建一个SimpleDateFormat对象,多线程访问无需争用。 

代码还要很多待改进的地方,如对于非法的pattern不要缓存,是否存在更快、更节约内存的方法。。。。。。 
匆匆忙忙,如有错误的地方望不吝赐教!

分享到:
评论

相关推荐

    DateFormat多线程问题

    总结来说,`DateFormat`的线程安全性问题要求开发者在多线程环境中特别注意其使用方式。通过理解这些潜在风险,我们可以采用适当的策略,如使用`ThreadLocal`,每次都创建新实例,或者切换到更现代的日期时间API,以...

    Java DateFormat并发实现

    然而,`DateFormat`并不是线程安全的,这意味着在多线程环境中直接使用可能会导致数据不一致或者异常。这篇博客文章《Java DateFormat并发实现》探讨了这个问题以及如何在并发环境下正确地使用`DateFormat`。 `...

    Java多线程编程中使用DateFormat类

    在Java多线程编程中,`DateFormat`类是一个常见的日期和时间格式化工具,但它并不是线程安全的。这意味着在多线程环境下直接共享`DateFormat`实例可能会导致数据不一致或者异常。根据Java官方文档的建议,每个线程...

    深入理解Java:SimpleDateFormat安全的时间格式化

    但是,如果使用不小心会导致非常微妙和难以调试的问题,因为DateFormat和SimpleDateFormat类不是线程安全的。在多线程环境下调用format()和parse()方法应该使用同步代码来避免问题。 知识点1: SimpleDateFormat的非...

    Java SimpleDateFormat线程安全问题原理详解

    如果需要在多线程环境下使用SimpleDateFormat,可以使用ThreadLocal或FastDateFormat确保线程安全。 Java SimpleDateFormat线程安全问题是Java开发中一个常见的问题。通过使用ThreadLocal或FastDateFormat,我们...

    Java ThreadLocal 线程安全问题解决方案

    Java中的ThreadLocal是解决线程安全问题的一个重要工具,它提供了一种在多线程环境下为每个线程维护独立变量副本的方法,从而避免了共享状态带来的竞态条件和线程安全问题。 线程安全问题通常由全局变量和静态变量...

    Java日期时间使用总结及项目中遇到的问题

    因为`Date`和`Calendar`类不是线程安全的,所以在多线程环境中使用时需要额外注意同步。另外,`SimpleDateFormat`是不可变的,但它的内部`DateFormat`是可变的,因此在多线程环境下,建议每个线程都拥有自己的`...

    解析Date & Calendar类

    - **java.text.DateFormat**: 是一个抽象类,用于格式化日期和时间。`SimpleDateFormat`是其具体子类,可以自定义日期和时间的格式。 - **日期计算**: 对于复杂的日期计算,如加减天数,可以使用Calendar类的...

    获取当前时间

    - 在高并发或多线程环境下使用 `DateFormat` 时,由于它是非线程安全的,需要通过同步机制来避免潜在的问题。例如,可以通过使用 `ThreadLocal` 来缓存每个线程的 `DateFormat` 实例。 4. **安全性问题**: - 当...

    Java在并发环境中SimpleDateFormat多种解决方案

    要在高并发环境下能有比较好的体验,可以使用ThreadLocal来限制SimpleDateFormat只能在线程内共享,这样就避免了多线程导致的线程安全问题。 ```java private static ThreadLocal&lt;DateFormat&gt; threadLocal = new ...

    核心Java 2 第2卷(第7版)

    本书覆盖了Java编程的各个方面,包括多线程、网络编程、I/O流、反射、集合框架、异常处理、国际化、安全、XML处理以及Java应用程序和Applet的开发等核心内容。以下是对这些主题的详细解释: 1. **多线程**:Java...

    findbug 常见异常处理

    Multithreaded correctness: 多线程正确性 Performance:性能 Security:安全 Dodgy: 欺骗性代码 2、 常见Bug以及处理办法 a) 不需要处理 May expose internal representation by incorporating reference to mutable...

    Java2 类库参考手册-pdf.zip

    在Java 2平台上,类库主要分为几个关键部分:基础类库、集合框架、IO流、网络编程、多线程、异常处理、反射、安全性和国际化等。以下将分别对这些方面进行详细介绍: 1. **基础类库**:这是Java语言的基础,包括...

    java程序的设计的编程.doc

    在上述文档中,我们看到四个不同的Java程序示例,分别涉及到基础的循环结构、条件判断、面向对象编程以及多线程与图形用户界面(GUI)。 1. **循环结构**:在第一个程序`Sum.java`中,使用了`for`循环来计算1到99...

    由浅入深解析 SimpleDateFormat

    1. SimpleDateFormat 是线程不安全的,因此在多线程环境下使用需要特别注意。 2. 创建 SimpleDateFormat 实例需要消耗大量的资源,因此应当尽量少创建实例。 3. SimpleDateFormat 可以使用 applyPattern 方法修改...

    java 6 api

    3. **多线程**:Java 6 API支持多线程编程,Thread类和Runnable接口是主要的多线程组件。通过继承Thread或实现Runnable,可以创建并管理多个并发执行的任务,利用多核处理器的性能。 4. **网络编程**:Java 6提供了...

    Java中SimpleDateFormat用法详解

    需要注意的是,`SimpleDateFormat`不是线程安全的,所以在多线程环境中,如果多个线程同时使用一个`SimpleDateFormat`实例,可能会出现错误。为了避免这个问题,可以在每个线程内部创建单独的实例,或者使用`...

    B3LOG Solo v1.0.0 for MySQL.zip

    169 DateFormat 线程安全问题 170 登录页面底部链接问题 172 GAE 版配额消耗过快问题 177 泄漏用户密码安全问题 129 摘要编辑器添加源码功能 132 Markdown 编辑器显示问题 154 使用密文存储密码 155 邮件 SSL...

    JDK API 中文帮助文档 1.6

    同步机制,如synchronized关键字、Lock接口及其实现,确保了多线程环境下的数据安全。 6. **反射**:Java反射API允许在运行时检查类、接口、字段和方法的信息,甚至动态调用方法和创建对象。这在元编程和插件系统中...

Global site tag (gtag.js) - Google Analytics