在此稍微解释一下ThreadLocal和线程同步,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
大致意思:Tim Cull碰到一个SimpleDateFormat带来的严重的性能问题,该问题主要有SimpleDateFormat引发,创建一个 SimpleDateFormat实例的开销比较昂贵,解析字符串时间时频繁创建生命周期短暂的实例导致性能低下。即使将 SimpleDateFormat定义为静态类变量,貌似能解决这个问题,但是SimpleDateFormat是非线程安全的,同样存在问题,如果用 ‘synchronized’线程同步同样面临问题,同步导致性能下降(线程之间序列化的获取SimpleDateFormat实例)。
Tim Cull使用Threadlocal解决了此问题,对于每个线程SimpleDateFormat不存在影响他们之间协作的状态,为每个线程创建一个SimpleDateFormat变量的拷贝或者叫做副本,代码如下:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 使用ThreadLocal以空间换时间解决SimpleDateFormat线程安全问题。
* @author
*
*/
public class DateUtil {
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
@SuppressWarnings("rawtypes")
private static ThreadLocal threadLocal = new ThreadLocal() {
protected synchronized Object initialValue() {
return new SimpleDateFormat(DATE_FORMAT);
}
};
public static DateFormat getDateFormat() {
return (DateFormat) threadLocal.get();
}
public static Date parse(String textDate) throws ParseException {
return getDateFormat().parse(textDate);
}
}
创建一个ThreadLocal类变量,这里创建时用了一个匿名类,覆盖了initialValue方法,主要作用是创建时初始化实例。也可以采用下面方式创建;
//第一次调用get将返回null
private static ThreadLocal threadLocal = new ThreadLocal();
//获取线程的变量副本,如果不覆盖initialValue,第一次get返回null,故需要初始化一个SimpleDateFormat,并set到threadLocal中
public static DateFormat getDateFormat()
{
DateFormat df = (DateFormat) threadLocal.get();
if(df==null){
df = new SimpleDateFormat(DATE_FORMAT)
threadLocal.set(df);
}
return df;
}
我们看下我们覆盖的initialValue方法:
protected T initialValue() {
return null;//直接返回null
}
当然也可以使用:
apache commons-lang包的DateFormatUtils或者FastDateFormat实现,apache保证是线程安全的,并且更高效。
分享到:
相关推荐
目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug的原因如何解决SimpleDateFormat多线程安全问题局部变量使用...
在Java编程语言中,`SimpleDateFormat`类是一个广泛使用的日期时间格式化工具,但它的线程安全性是一个常常被开发者忽视的问题。标题指出的"simpleDateFormat是线程不安全的",意味着在多线程环境下,如果多个线程...
SimpleDateFormat类的线程安全问题和解决方案 SimpleDateFormat类的线程安全问题 SimpleDateFormat类是Java提供的日期时间转化类,用于将日期和时间类型的数据进行解析和格式化。在Java开发中,SimpleDateFormat类...
### 关于SimpleDateFormat的非线程安全问题及其解决方案 #### 一、问题介绍 在Java开发过程中,`SimpleDateFormat`是被广泛使用的日期格式化工具类。然而,在多线程环境下,`SimpleDateFormat`存在非线程安全的...
为了解决SimpleDateFormat非线程安全性的问题,可以使用同步代码来避免问题。例如,可以使用synchronized关键字来同步访问SimpleDateFormat实例,也可以使用ThreadLocal变量来保存每个线程的SimpleDateFormat实例。 ...
本文将深入探讨`SimpleDateFormat`的线程安全问题及其解决方案。 ### 1. 线程安全问题的原因 `SimpleDateFormat`内部维护了一个`Calendar`对象,用于处理日期和时间的解析与格式化。由于`SimpleDateFormat`不是...
nable() { @Override public void run() { // 定义局部变量 SimpleDateFormat SimpleDateFormat simpleDateFormat = new ...根据实际应用场景,可以选择适合的解决方案以确保线程安全并提高程序的并发性能。
假设我们有一个非线程安全的变量需要转换为线程安全的变量。通常的做法是使用同步机制将对象封装到同步块中,但这可能会导致性能瓶颈。另一种更高效的方式是使用ThreadLocal,为每个线程持有一个独立的对象副本,...
为了解决SimpleDateFormat类的线程安全问题,可以使用ThreadLocal类。ThreadLocal类可以使线程绑定到指定的对象,从而避免了线程之间的对象共享问题。在示例代码中,我们使用ThreadLocal类来绑定SimpleDateFormat...
Java中的ThreadLocal是解决线程安全问题的一个重要工具,它提供了一种在多线程环境下为每个线程维护独立变量副本的方法,从而避免了共享状态带来的竞态条件和线程安全问题。 线程安全问题通常由全局变量和静态变量...
Java SimpleDateFormat线程安全问题原理详解 Java SimpleDateFormat线程安全问题是Java开发中一个常见的问题。SimpleDateFormat是Java中一个常用的日期时间格式化类,但是它却存在线程安全问题。在多线程环境下,...
Java ThreadLocal是Java语言中的一种机制,用于为每个线程提供一个独立的变量副本,以解决多线程环境下共享变量的线程安全问题。在本文中,我们将详细介绍Java ThreadLocal的使用案例,并通过一个实际的优化案例,...
在多线程环境中,避免使用非线程安全的类如`SimpleDateFormat`,因为它可能导致不可预测的行为或数据不一致。为确保线程安全,可以使用`ThreadLocal`来存储线程专属的实例,或者使用Java 8及更高版本的日期时间API,...
`SimpleDateFormat`是`DateFormat`的一个具体实现,它也是非线程安全的。在并发情况下,可以使用同步块或者静态工厂方法来创建新的`SimpleDateFormat`实例,确保在每次需要格式化或解析日期时都创建新的对象。 ```...
Java 8 引入了`java.time.format.DateTimeFormatter`,这个类是线程安全的,可以作为`SimpleDateFormat`的一个更优选择。它提供了与`SimpleDateFormat`类似的功能,但避免了线程安全问题。 5. **池化`DateFormat`...
* SimpleDateFormat类不是线程安全的,因为它使用了非线程安全的Calendar对象。 * 解决线程安全问题可以使用ThreadLocal、Lock、Atomic变量等方式。 五、线程池的重要性 * 线程池可以重用线程,减少线程创建和销毁...
要在高并发环境下能有比较好的体验,可以使用ThreadLocal来限制SimpleDateFormat只能在线程内共享,这样就避免了多线程导致的线程安全问题。 ```java private static ThreadLocal<DateFormat> threadLocal = new ...
- **SimpleDateFormat非线程安全**:在多线程环境下,使用ThreadLocal封装SimpleDateFormat以保证线程安全,或者使用日期处理库如joda-time。 4. **面向对象和设计原则**: - **SOLID原则**:单一职责、开闭原则...