有三种方法可以解决以上安全问题。
  1).使用同步

 package com.bijian.study.date;

 import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class DateUtil02 implements DateUtilInterface { private SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Override
public void format(Date date) {
System.out.println(dateformat.format(date));
} @Override
public void parse(String str) {
try {
synchronized(dateformat){
System.out.println(dateformat.parse(str));
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}

修改DateMainTest.java的DateUtilInterface dateUtil = new DateUtil01();为DateUtilInterface dateUtil = new DateUtil02();测试OK。

不过,当线程较多时,当一个线程调用该方法时,其他想要调用此方法的线程就要block,这样的操作也会一定程度上影响性能。

2).每次使用时,都创建一个新的SimpleDateFormat实例

 package com.bijian.study.date;

 import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class DateUtil03 implements DateUtilInterface { @Override
public void format(Date date) { SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(dateformat.format(date));
} @Override
public void parse(String str) {
try {
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(dateformat.parse(str));
} catch (ParseException e) {
e.printStackTrace();
}
}
}

修改DateMainTest.java的DateUtilInterface dateUtil = new DateUtil02();为DateUtilInterface dateUtil = new DateUtil03();测试OK。

3).借助ThreadLocal对象每个线程只创建一个实例

借助ThreadLocal对象每个线程只创建一个实例,这是推荐的方法

对于每个线程SimpleDateFormat不存在影响他们之间协作的状态,为每个线程创建一个SimpleDateFormat变量的拷贝或者叫做副本,代码如下:

 package com.bijian.study.date;

 import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class DateUtil04 implements DateUtilInterface { private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; // 第一次调用get将返回null
private static ThreadLocal threadLocal = new ThreadLocal(){
protected Object initialValue() {
return null;//直接返回null
}
}; // 获取线程的变量副本,如果不覆盖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;
} @Override
public void parse(String textDate) { try {
System.out.println(getDateFormat().parse(textDate));
} catch (ParseException e) {
e.printStackTrace();
}
} @Override
public void format(Date date) {
System.out.println(getDateFormat().format(date));
}
}

创建一个ThreadLocal类变量,这里创建时用了一个匿名类,覆盖了initialValue方法,主要作用是创建时初始化实例。

也可以采用下面方式创建。

 package com.bijian.study.date;

 import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class DateUtil05 implements DateUtilInterface { 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 DateFormat getDateFormat() {
return (DateFormat) threadLocal.get();
} @Override
public void parse(String textDate) { try {
System.out.println(getDateFormat().parse(textDate));
} catch (ParseException e) {
e.printStackTrace();
}
} @Override
public void format(Date date) {
System.out.println(getDateFormat().format(date));
}
}

修改DateMainTest.java的DateUtilInterface dateUtil = new DateUtil03();为DateUtilInterface dateUtil = new DateUtil04();或者DateUtilInterface dateUtil = new DateUtil05();测试OK。

最后,当然也可以使用apache commons-lang包的DateFormatUtils或者FastDateFormat实现,apache保证是线程安全的,并且更高效。

附:Oracle官方bug说明: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6178997

  转自 http://bijian1013.iteye.com/blog/1873336

SimpleDateFormat线程不安全(转)的更多相关文章

  1. SimpleDateFormat线程不安全及解决办法

    原文链接:https://blog.csdn.net/csdn_ds/article/details/72984646 以前没有注意到SimpleDateFormat线程不安全的问题,写时间工具类,一 ...

  2. SimpleDateFormat线程不安全及解决办法(转)

    以前没有注意到SimpleDateFormat线程不安全的问题,写时间工具类,一般写成静态的成员变量,不知,此种写法的危险性!在此讨论一下SimpleDateFormat线程不安全问题,以及解决方法. ...

  3. SimpleDateFormat线程不安全原因及解决方案

    一. 线程不安全验证: /** * SimpleDateFormat线程安全测试 * 〈功能详细描述〉 * * @author 17090889 * @see [相关类/方法](可选) * @sinc ...

  4. SimpleDateFormat线程不安全的5种解决方案!

    1.什么是线程不安全? 线程不安全也叫非线程安全,是指多线程执行中,程序的执行结果和预期的结果不符的情况就叫做线程不安全. ​ 线程不安全的代码 SimpleDateFormat 就是一个典型的线程不 ...

  5. SimpleDateFormat线程不安全问题处理

    在工作中,通过SimpleDateFormat将字符串类型转为日期类型时,发现有时返回的日期类型出错,调用方法如下: public final class DateUtil { static fina ...

  6. SimpleDateFormat 线程不安全及解决方案

    SimpleDateFormat定义 SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类.它允许进行格式化(日期 -> 文本).解析(文本 -> 日期 ...

  7. SimpleDateFormat线程不安全及解决的方法

    一. 为什么SimpleDateFormat不是线程安全的? Java源代码例如以下: /** * Date formats are not synchronized. * It is recomme ...

  8. 解决SimpleDateFormat线程安全问题

    package com.tanlu.user.util; import java.text.DateFormat; import java.text.ParseException; import ja ...

  9. SimpleDateFormat线程不安全问题解决及替换方法

    场景:在多线程情况下为避免多次创建SimpleDateForma实力占用资源,将SimpleDateForma对象设置为static. 出现错误:SimpleDateFormat定义为静态变量,那么多 ...

随机推荐

  1. 12.HTML DOM 允许 JavaScript 改变 HTML 元素的内容。

    1,改变 HTML 输出流 <script> document.write(Date()); </script> 2,改变 HTML 内容 <script> doc ...

  2. 腾讯云服务器申请免费SSL证书,实现Https。

    1.首先在腾讯云的SSL证书管理中申请免费的SSL.审核速度还是挺快的... 2.按照步骤申请后,就可以下载主流web服务器的证书了.如图: 3.这里我使用的web服务器是nginx,把nginx下的 ...

  3. ABAP- INCLUDE Zxxx IF FOUND.

    大顾代码: INCLUDE zinc_ca_0002 IF FOUND. - 这肯定是大顾问写出来的 - 一般都不会加东西啊 -加了 IF FOUND 不知道啥意思.  古道无仙(173120830) ...

  4. KeyChain相关参数的说明

    #pragma mark- 密钥类型 //密钥类型键 //CFTypeRef kSecClass // //值 //CFTypeRef kSecClassGenericPassword         ...

  5. 在windows下把Mongodb设置系统服务

    把Mongodb Server 设置为系统,方便启动与停止 今天一时兴起在本地安装了下Mongodb服务,安装完后,创建了配置文件为数据库服务指明在哪里存储数据库原始文件,随即就启动了mongo se ...

  6. BZOJ 1632 [Usaco2007 Feb]Lilypad Pond:spfa【同时更新:经过边的数量最小】【路径数量】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1632 题意: 有一个n*m的池塘.0代表水,1代表荷花,2代表岩石,3代表起点,4代表终点 ...

  7. [原创]java对word文档的在线打开

    一.材料准备 百度一下:PageOffice,从官网下载PageOffice for Java.压缩包文件: 二. 实现步骤: 1. 打开“集成文件”目录,拷贝“WEB-INF\lib”目录中的pag ...

  8. bzoj 2155 Xor

    题目大意: 求一条从$1 \rightarrow n$的路径是异或和最大 思路: 先随便求一棵生成树,然后求出所有环,对于所有环都可以去转一圈只取到这个环的贡献 那么就是线性基裸题了 #include ...

  9. Oracle数据常用操作

    将用逗号隔开字段拆分成两行: select * from mp_fs_file_info a,dm_process_upload b where instr(b.attachment,a.file_i ...

  10. Codeforces Round #535(div 3) 简要题解

    Problem A. Two distinct points [题解] 显然 , 当l1不等于r2时 , (l1 , r2)是一组解 否则 , (l1 , l2)是一组合法的解 时间复杂度 : O(1 ...