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定义为静态变量,那么多 ...
随机推荐
- Transforming Auto-encoders
http://www.cs.toronto.edu/~hinton/absps/transauto6.pdf The artificial neural networks that are used ...
- ReentrantLock(重入锁)简单源码分析
1.ReentrantLock是基于AQS实现的一种重入锁. 2.先介绍下公平锁/非公平锁 公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公平锁 非公平锁是指多个线程获取锁的顺序并不是按照申 ...
- python网络爬虫之使用scrapy爬取图片
在前面的章节中都介绍了scrapy如何爬取网页数据,今天介绍下如何爬取图片. 下载图片需要用到ImagesPipeline这个类,首先介绍下工作流程: 1 首先需要在一个爬虫中,获取到图片的url并存 ...
- 【网络基础系列二】BOOTP、DHCP协议
BOOTP 含义:BOOT Protocol,引导协议 作用:引导无盘计算机或者第一次启动的计算机获取以下网络配置信息: 主机的IP地址.子网掩码 路由器(网关)的IP地址 DNS服务器IP地址 C/ ...
- Mac终端操作SVN指令
1.将文件checkout到本地目录 svn checkout path(path是服务器上的目录) 例如:svn checkout svn://192.168.1.1/pro/domain ...
- 分布式锁(Zookeeper实现)
分布式锁 分布式锁,这个主要得益于 ZooKeeper 为我们保证了数据的强一致性.锁服务可以分为两类,一个是 保持独占,另一个是 控制时序. 1. 所谓保持独占,就是所有试图来获取这个锁的客户端,最 ...
- 学习c编程的第二天
函数又叫方法,是实现某项功能或完成某项任务的代码块 #include<stdio.h>void show(){ printf("I like c language"); ...
- 提取html的正文
1 using System; 2 using System.Text; 3 namespace HtmlStrip 4 { 5 class MainClass 6 { 7 ...
- Linux中进程控制块PCB-------task_struct结构体结构
Linux中task_struct用来控制管理进程,结构如下: struct task_struct { //说明了该进程是否可以执行,还是可中断等信息 volatile long state; // ...
- android 通过包名过滤logcat
#!/bin/bash ]]; then cat <<EOF Usage: `` <packagename> EOF exit package_name=$ ip= pid_l ...