有三种方法可以解决以上安全问题。
  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

最新文章

  1. Fresco内存机制(Ashmem匿名共享内存)
  2. js中var 笔记
  3. PHP include()和require()方法的区别
  4. c++中智能输出文件
  5. 监控SQL Server的job执行情况
  6. hdu 5144 NPY and shot
  7. ftk学习记(waitbox篇)
  8. 移动端页面 iPhone + Safari 页面调试 之 正确查看网络请求的姿势
  9. BZOJ 2388: 旅行规划 [分块 凸包 等差数列]
  10. 2018年多校第四场第二题 B. Harvest of Apples hdu6333
  11. 工作小结:xml文件导入到oracle
  12. windows安装composer
  13. Android gravity和layout_gravity的区别
  14. Oracle分析函数row_number()等的使用实例
  15. 安装istio v1.0 详细过程和步骤
  16. Linux:Apache安装与启动
  17. React设置宽度的坑
  18. adb 调试出现问题
  19. asp.net读取用户控件,自定义加载用户控件
  20. xml常用的error-page

热门文章

  1. IDEA eclipse 控制台日志输出到文件
  2. 关于web页自动适配屏幕大小
  3. CSS Overflow 属性清除浮动
  4. DIY固件系列教程——实现开机LOGO三屏动画的完全替换【转】
  5. Gym - 100676E —— 基础题
  6. Oracle中视图和同义词的区别
  7. MYSQL进阶学习笔记十四:MySQL 应用程序优化!(视频序号:进阶_32)
  8. Program received signal SIGSEGV, Segmentation fault.
  9. 查看系统信息,区分Centos和Ubuntu
  10. 模仿yui将css和js打包,加速网页速度