SimpleDateFormat线程不安全(转)
有三种方法可以解决以上安全问题。
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
SimpleDateFormat线程不安全(转)的更多相关文章
- SimpleDateFormat线程不安全及解决办法
原文链接:https://blog.csdn.net/csdn_ds/article/details/72984646 以前没有注意到SimpleDateFormat线程不安全的问题,写时间工具类,一 ...
- SimpleDateFormat线程不安全及解决办法(转)
以前没有注意到SimpleDateFormat线程不安全的问题,写时间工具类,一般写成静态的成员变量,不知,此种写法的危险性!在此讨论一下SimpleDateFormat线程不安全问题,以及解决方法. ...
- SimpleDateFormat线程不安全原因及解决方案
一. 线程不安全验证: /** * SimpleDateFormat线程安全测试 * 〈功能详细描述〉 * * @author 17090889 * @see [相关类/方法](可选) * @sinc ...
- SimpleDateFormat线程不安全的5种解决方案!
1.什么是线程不安全? 线程不安全也叫非线程安全,是指多线程执行中,程序的执行结果和预期的结果不符的情况就叫做线程不安全. 线程不安全的代码 SimpleDateFormat 就是一个典型的线程不 ...
- SimpleDateFormat线程不安全问题处理
在工作中,通过SimpleDateFormat将字符串类型转为日期类型时,发现有时返回的日期类型出错,调用方法如下: public final class DateUtil { static fina ...
- SimpleDateFormat 线程不安全及解决方案
SimpleDateFormat定义 SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类.它允许进行格式化(日期 -> 文本).解析(文本 -> 日期 ...
- SimpleDateFormat线程不安全及解决的方法
一. 为什么SimpleDateFormat不是线程安全的? Java源代码例如以下: /** * Date formats are not synchronized. * It is recomme ...
- 解决SimpleDateFormat线程安全问题
package com.tanlu.user.util; import java.text.DateFormat; import java.text.ParseException; import ja ...
- SimpleDateFormat线程不安全问题解决及替换方法
场景:在多线程情况下为避免多次创建SimpleDateForma实力占用资源,将SimpleDateForma对象设置为static. 出现错误:SimpleDateFormat定义为静态变量,那么多 ...
随机推荐
- 各种数据库(oracle、mysql、sqlserver等)在Spring中数据源的配置和JDBC驱动包----转
在开发基于数据库的应用系统时,需要在项目中进行数据源的配置来为数据 库的操作取得数据库连接.配置不同数据库的数据源的方法大体上都是相同的,不同的只是不同数据库的JDBC驱动类和连接URL以及相应的数据 ...
- JSOI2004 平衡点 / 吊打XXX
题目描述 有n个重物,每个重物系在一条足够长的绳子上.每条绳子自上而下穿过桌面上的洞,然后系在一起.图中X处就是公共的绳结.假设绳子是完全弹性的(不会造成能量损失),桌子足够高(因而重物不会垂到地上) ...
- go 客户端服务端通信
client.go package main import ( "bufio" "encoding/json" "fmt" "ha ...
- 自动化测试框架selenium+java+TestNG——配置篇
最近来总结下自动化测试 selenium的一些常用框架测试搭配,由简入繁,最简单的就是selenium+java+TestNG了,因为我用的是java,就只是总结下java了. TestNG在线安装: ...
- windows 下python搭建环境
一.python安装 1,首先访问https://www.python.org/downloads/windows/去下载python版本. 2. 选择3.5版本,installer文件类型(因为3. ...
- poj3181【Dollar Dayz】
做完这道题,心里五味陈杂,明明是最水的一道题,我却做了最长的时间. 题意是求用1-k的和表示n的方案数. 显然是个计数dp,但我不会.思考半小时未果. 然后找尹鹏哲,他给我讲了个错的dp方程,结果调试 ...
- BZOJ2006:超级钢琴(ST表+堆求前K大区间和)
Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度 ...
- Azure REST API (5) 中国Azure EA Portal Billing API
<Windows Azure Platform 系列文章目录> 本文介绍的是国内由世纪互联运维的Azure China. EA Portal的管理url是:https://ea.azure ...
- Winform安装包出现无法访问网络位置
1.原因:安装包的安装路径出现了问题 2.如下图:错误路径 3.如下图:正确路径
- Day02:数据类型、字符编码、文件处理
一.基础数据类型与其内置方法 1. int基本使用:int(3.1) 用途:记录年龄,职级等 只能将包含纯数字的字符串类型转换成整形 特点:1.存一个值. 2.不可变 2.float基本使用 floa ...