`
hanyi366
  • 浏览: 284180 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

多线程下使用 SimpleDateFormat 的问题

    博客分类:
  • Java
 
阅读更多

最近用到多线程写通信服务,发现在解析时间是一直莫名的错误,最后获取的时间和设备给我传输的时间经常不一致,时间有0144-12-12、2144-02-12等。很莫名其妙!

 

经过分析得出在转换时间时使用了SimpleDateFormat ,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方法,主要作用是创建时初始化实例。也可以采用下面方式创建;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

/**
 * 使用ThreadLocal以空间换时间解决SimpleDateFormat线程安全问题。
 * 
 * @author
 * 
 */
public class DateUtil {

    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    // 第一次调用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保证是线程安全的,并且更高效。

备注:没有找到相应的prase 方法。 

 

分享到:
评论

相关推荐

    ThreadLocal:如何优雅的解决SimpleDateFormat多线程安全问题

    目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug的原因如何解决SimpleDateFormat多线程安全问题局部变量使用...

    Java多线程环境下SimpleDateFormat类安全转换

    主要介绍了Java多线程环境下SimpleDateFormat类安全转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    Java多线程编程的线程安全性.docx

    Java标准库中的一些类如ArrayList、HashMap和SimpleDateFormat,都是非线程安全的,在多线程环境下直接使用它们可能导致一些非预期的结果,甚至是一些灾难性的结果。一般来说,Java标准库中的类在其API文档中会说明...

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

    Java 中一个非常常用的类,该类用来对日期字符串进行解析和格式化输出,但如果使用不小心会导致非常微妙和难以调试的问题,因为 DateFormat 和 SimpleDateFormat 类不都是线程安全的,在多线程环境下调用 ...

    JavaSE 之 传统日期格式化的线程问题

    需求:让多线程同时去解析日期 错误示范 public class Test1 { @Test public void test01() throws Exception { //格式化日期类 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); //任务类:用于...

    java大学实用教程课件

    Java语言是面向对象编程,并涉及到网络、多线程等重要的基础知识,而且很多新的技术领域都涉及到了Java语言,因此,学习和掌握Java已成为共识,国内外许多大学已将Java语言列入了本科教学计划,IT行业对Java人才的...

    基础深化和提高-常用类

    Java常用类指的是Java标准库中提供的一些常用的类,这些类提供了丰富的功能和工具,...Thread、Executor、Lock、Semaphore等:用于支持多线程编程,提供了线程管理、同步和互斥的工具。 网络编程类: Socket、ServerS

    JAVA基础课程讲义

    通过Runnable接口实现多线程 169 线程状态和sleep/yield/join/stop/destroy方法 170 新生状态 170 就绪状态 170 运行状态 170 死亡状态 170 终止线程的典型方法(重要!!!) 171 阻塞状态(sleep/yield/join方法) ...

    Java范例开发大全(全书源程序)

    实例194 使用SimpleDateFormat类获取系统的当前时间 329 实例195 显示某年某月某一周的信息 330 实例196 显示某年某月的信息 332 实例197 时间的设置与获取 334 实例198 万年历(农历和阳历的互换) 337 11.4 ...

    Java基础知识点.html

    类加载器 ClassLoader 反射 Stream 流 函数式编程 Lambda 表达式 网络编程-协议 网络编程-端口 网络编程-IP 多线程 IO流-字节流 IO流-字符流 IO流-转换流 File Map HashMap 序列化和反序列化 可变参数 类型通配符 ...

    Java开发技术大全 电子版

    13.5.2使用SimpleDateFormat格式化输出时间405 13.5.3Calendar类的特色408 13.5.4利用GregorianCalendar输出日历411 13.6Formatter类的使用413 13.6.1Formatter的简单使用413 13.6.2时间格式转换符详解415 ...

    Java范例开发大全 (源程序)

     实例194 使用SimpleDateFormat类获取系统的当前时间 329  实例195 显示某年某月某一周的信息 330  实例196 显示某年某月的信息 332  实例197 时间的设置与获取 334  实例198 万年历(农历和阳历的互换) ...

    java范例开发大全(pdf&源码)

    实例194 使用SimpleDateFormat类获取系统的当前时间 329 实例195 显示某年某月某一周的信息 330 实例196 显示某年某月的信息 332 实例197 时间的设置与获取 334 实例198 万年历(农历和阳历的互换) 337 11.4 ...

    java范例开发大全源代码

     实例194 使用SimpleDateFormat类获取系统的当前时间 329  实例195 显示某年某月某一周的信息 330  实例196 显示某年某月的信息 332  实例197 时间的设置与获取 334  实例198 万年历(农历和阳历的互换...

    java范例开发大全

    实例194 使用SimpleDateFormat类获取系统的当前时间 329 实例195 显示某年某月某一周的信息 330 实例196 显示某年某月的信息 332 实例197 时间的设置与获取 334 实例198 万年历(农历和阳历的互换) 337 11.4 ...

    java面试题

    答:Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式允许其service方法,一个实例可以服务于多个请求,并且其实例一般不会被销毁,而CGI对每个请求都产生新的进程,服务完后就销毁,所以效率上...

    Java开发详解.zip

    030901_【第9章:多线程】_认识多线程笔记.pdf 030902_【第9章:多线程】_线程常用操作方法笔记.pdf 030903_〖第9章:多线程〗_线程操作范例笔记.pdf 030904_【第9章:多线程】_同步与死锁笔记.pdf 030905_【第9章:...

    java内部学习笔记.docx

    Java技术基础 4 1.1编程语言 4 1.2 Java的特点 4 1.3 Java开发环境 4 1.4 Java开发环境配置 5 1.5 Linux命令与相关知识 5 ...5.12 Thread线程类及多线程 61 5.13 Socket网络编程 65 5.14线程池 67 5.15双缓冲队列 68

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例143 使用线程池优化多线程编程 186 实例144 Object类中线程相关的方法 187 实例145 哲学家就餐问题 189 实例146 使用信号量实现线程同步 190 实例147 使用原子变量实现线程同步 191 实例148 使用事件分配线程...

Global site tag (gtag.js) - Google Analytics