由于项目是运行在多线程环境下的,SimpleDateFormat对于日期的转换就出问题了。昨天测试部邮件通知我们日志的开始时间大于结束时间的时候我头都大了。经查找,发现是由于SimpleDateFormat线程不安全引起的。哎,以前一直在用这个类,从来没关注过。
现将测试代码发上。
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang.time.FastDateFormat;
public class Main {
private static final DateFormatUtils dateUtil = new DateFormatUtils();
private static final SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss.SSS");
private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
private SimpleDateFormat getFormat() {
SimpleDateFormat sdf = threadLocal.get();
if (sdf == null) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
threadLocal.set(sdf);
}
return sdf;
}
public void foo(Date d1, Date d2) throws ParseException {
String sd1 = getFormat().format(d1);
String sd2 = getFormat().format(d2);
Date dd1 = getFormat().parse(sd1);
Date dd2 = getFormat().parse(sd2);
if (dd1.getTime() - dd2.getTime() > 0) {
System.err.println("Error:" + sd1 + ">" + sd2);
}
}
public void foo2(Date d1, Date d2) throws ParseException {
String sd1 = DateFormatUtils.format(d1, "yyyy-MM-dd HH:mm:ss.SSS");
String sd2 = DateFormatUtils.format(d2, "yyyy-MM-dd HH:mm:ss.SSS");
Date dd1 = DateUtils.parseDate(sd1,
new String[] { "yyyy-MM-dd HH:mm:ss.SSS" });
Date dd2 = DateUtils.parseDate(sd1,
new String[] { "yyyy-MM-dd HH:mm:ss.SSS" });
if (dd1.getTime() - dd2.getTime() > 0) {
System.err.println("Error:" + sd1 + ">" + sd2);
}
}
public static void main(String[] args) throws ParseException {
Main m = new Main();
Thread thread1 = new Thread(new Thread1(m));
thread1.start();
Thread thread2 = new Thread(new Thread1(m));
thread2.start();
}
}
两个线程:
import java.text.ParseException;
import java.util.Date;
public class Thread1 implements Runnable{
private Main main;
public Thread1(Main main){
this.main = main;
}
public void run() {
for(;;){
try {
main.foo(new Date(), new Date());
} catch (ParseException e) {
e.printStackTrace();
}
}
}
}
import java.text.ParseException;
import java.util.Date;
public class Thread2 implements Runnable{
private Main main;
public Thread2(Main main){
this.main = main;
}
public void run() {
for(;;){
try {
main.foo2(new Date(), new Date());
} catch (ParseException e) {
e.printStackTrace();
}
}
}
}
如上,如果Main类中foo方法使用静态常量sdf进行转换很多错误的打印语句。如果使用ThreadLocal类绑定SimpleDateFormat则可以解决线程不统一的问题。
当然使用Apache提供的类DateFormatUtils以及DateUtils类进行日期的转换也可以解决线程的问题,如foo2方法。
分享到:
相关推荐
在Java编程语言中,`SimpleDateFormat`类是一个广泛使用的日期时间格式化工具,但它的线程安全性是一个常常被开发者忽视的问题。标题指出的"simpleDateFormat是线程不安全的",意味着在多线程环境下,如果多个线程...
SimpleDateFormat类的线程安全问题和解决方案 SimpleDateFormat类的线程安全问题 SimpleDateFormat类是Java提供的日期时间转化类,用于将日期和时间类型的数据进行解析和格式化。在Java开发中,SimpleDateFormat类...
目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现...事项使用ThreadLocal解决SimpleDateFormat线程安全问题总结...
然后在你的代码中,通过`SafeDateFormat.getInstance()`获取线程安全的`SimpleDateFormat`实例。 #### 3.2. 每次使用时创建新的`SimpleDateFormat`实例 另一种解决方法是在每次需要格式化或解析日期时,都创建一个...
SimpleDateFormat线程不安全的5种解决方案.md
JDK 8 引入了新的日期时间 API,其中的 DateTimeFormatter 是线程安全的,可以替代 SimpleDateFormat。以下是使用 DateTimeFormatter 的示例: ```java import java.time.LocalDateTime; import java.time.format....
3. **使用不可变的日期时间API**:从Java 8开始,提供了新的日期时间API(如`java.time`包下的类),这些API设计为线程安全的,可以替代`SimpleDateFormat`。 ```java import java.time.LocalDate; import java....
但是,如果使用不小心会导致非常微妙和难以调试的问题,因为DateFormat和SimpleDateFormat类不是线程安全的。在多线程环境下调用format()和parse()方法应该使用同步代码来避免问题。 知识点1: SimpleDateFormat的非...
SimpleDateFormat类是Java中常用的日期格式化类,但是它并不是线程安全的。在多线程环境下,如果多个线程同时使用同一个SimpleDateFormat对象,可能会出现日期格式化错误的问题。 2. 使用ThreadLocal解决线程安全...
Java SimpleDateFormat线程安全问题原理详解 Java SimpleDateFormat线程安全问题是Java开发中一个常见的问题。SimpleDateFormat是Java中一个常用的日期时间格式化类,但是它却存在线程安全问题。在多线程环境下,...
SimpleDateFormat 详解 SimpleDateFormat 是 Java 语言中...然而,在使用时需要注意线程安全和资源消耗问题。通过合理地使用 SimpleDateFormat,我们可以实现日期和时间的高效格式化和解析,提高程序的性能和可读性。
这类类在设计时就没有考虑线程安全,例如`SimpleDateFormat`,在1.4 JDK之前的版本中并未明确指出其线程不安全,导致许多开发者在并发场景中误用,引发错误。 在文档中清晰地记录类的线程安全性是至关重要的。如...
Java标准库中有一些类,如ArrayList、HashMap和SimpleDateFormat,并未设计为线程安全,因此在多线程环境下直接使用可能导致数据不一致或其他问题。开发者应当了解每个类的线程安全特性,以便做出正确的选择和适当地...
需要注意的是,由于`SimpleDateFormat`不是线程安全的,所以在多线程环境中,建议为每个线程创建单独的实例。 `Calendar`类则是Java中更底层的日期和时间工具,它提供了一套完整的API来操作日期和时间,包括添加、...
- `SimpleDateFormat`是线程不安全的,如果在多线程环境中使用,需要考虑同步问题。 - 日期和时间的格式化字符串要与实际情况对应,避免出现理解错误。 以上就是关于`SimpleDateFormat`的一些常见用法和注意事项,...
Java线程安全的计数器简单实现代码示例 Java线程安全的计数器简单实现代码示例是一种在Java中实现线程安全的计数器的方法,该方法使用AtomicInteger和volatile关键字来保证计数器的线程安全性。该计数器可以每天从1...
`SimpleDateFormat`不是线程安全的,所以在多线程环境中,要么为每个线程创建单独的实例,要么在每次使用后进行同步。 8. **替代方案**: Java 8引入了`java.time`包,其中的`DateTimeFormatter`类提供了更现代且...
Java 8 引入了`java.time.format.DateTimeFormatter`,这个类是线程安全的,可以作为`SimpleDateFormat`的一个更优选择。它提供了与`SimpleDateFormat`类似的功能,但避免了线程安全问题。 5. **池化`DateFormat`...
在多线程环境中,避免使用非线程安全的类如`SimpleDateFormat`,因为它可能导致不可预测的行为或数据不一致。为确保线程安全,可以使用`ThreadLocal`来存储线程专属的实例,或者使用Java 8及更高版本的日期时间API,...