今天给各位分享面试官一步步教你为什么SimpleDateFormat不是线程安全的的知识,其中也会对进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
采访者:您能写一下您是如何使用它的吗?
小小白:我打字完了,代码如下:
公共类SimpleDateFormatTest {
静态最终ThreadLocalDateFormat df=new ThreadLocalDateFormat() {
@覆盖
受保护的日期格式初始值(){
return new SimpleDateFormat(‘yyyy-MM-dd HH:mm:ss’);
}
};
公共静态无效主(字符串[] args){
尝试{
df.get().parse(‘2020-03-27 10:09:01’);
} catch (ParseException e) {
e.printStackTrace();
} 最后{
df.remove();
}
}
}
面试官:为什么要用ThreadLocal来包装SimpleDateFormat?
小白:如果不使用ThreadLocal对其进行包装,直接创建一个SimpleDateFormat共享实例对象,在多线程并发中使用该对象的方法是线程不安全的,可能会抛出NumberFormatException或者其他异常。使用ThreadLocal对其进行包装,每个线程都有自己的SimpleDateFormat实例对象,这样在多线程并发的情况下不会出现线程不安全的情况。
面试官:那为什么SimpleDateFormat作为共享变量是线程不安全的呢?
小小白:以下面的代码为例,解释一下原因。
公共类SimpleDateFormatTest {
私有静态最终SimpleDateFormat sdf=new SimpleDateFormat(‘yyyy-MM-dd HH:mm:ss SSS’);
公共静态无效主(字符串[] args){
for (int i=0; i=15; i++) {
新线程(新可运行(){
@覆盖
公共无效运行(){
尝试{
System.out.println(sdf.parse(‘2020-3-27 10:09:01’));
} catch (异常e) {
e.printStackTrace();
}
}
})。开始();
}
}
}
SimpleDateFormat 类继承了DateFormat 抽象类。 DateFormat抽象类中有一个Calendar类型的属性calendar,这是让SimpleDateFormat线程不安全的关键。上面代码中的变量sdf是全局共享的。首先,通过SimpleDateFormat构造方法创建对象,并进入该构造方法的源代码。
公共SimpleDateFormat(字符串模式)
{
this(pattern, Locale.getDefault(Locale.Category.FORMAT));
}
公共SimpleDateFormat(字符串模式,区域设置区域设置)
{
if (模式==null || 语言环境==null) {
抛出新的NullPointerException();
}
//初始化一个日历实例
初始化日历(区域设置);
this.pattern=模式;
this.formatData=DateFormatSymbols.getInstanceRef(locale);
this.locale=区域设置;
初始化(语言环境);
}
//如果DateFormat 中的日历属性等于null,则创建一个
私有无效initializeCalendar(区域设置loc){
如果(日历==空){
断言loc !=null;
//格式对象必须使用该区域的符号来构造。
//但是,日历应使用当前默认时区。
//如果区域设置区域字符串中不包含该区域,则该区域
//将使用通用GMT+/-H:MM 命名法进行格式化。
日历=Calendar.getInstance(TimeZone.getDefault(), loc);
}
}
在这个构造函数中,初始化了SimpleDateFormat的一些属性值,特别是calendar。接下来进入SimpleDateFormat类的parse方法的源代码。
公共日期解析(字符串源)抛出ParseException
{
ParsePosition pos=new ParsePosition(0);
//通过解析参数值source获取一个Date
日期结果=parse(source, pos);
if (pos.index==0)
抛出新的ParseException(‘无法解析的date: \” + source + ‘\” ,
pos.errorIndex);
返回结果;
}
//通过解析参数值source获取一个Date
//该方法代码较多,这里省略不重要的代码。
公共日期解析(字符串文本,ParsePosition pos)
{
//省略部分解析日期字符串的代码
CalendarBuilder calb=new CalendarBuilder();
//日期字符串解析完成后,存储到calb中
解析日期Date;
尝试{
//使用calb 中解析的日期数据设置日历
parsedDate=calb.built(calendar).getTime();
//省略一些代码
}
捕获(IllegalArgumentException e){
//省略一些代码
}
返回解析日期;
}
//CalendarBuilder类的create方法的部分代码
日历建立(Calendar cal) {
//省略一些不重要的代码
cal.clear();
//省略一些不重要的代码
返回校准;
}
从上面的代码可以看到,对传入的日期和时间字符串进行解析,然后将解析后的日期数据设置到日历中,这是通过create方法完成的。请注意,此方法中调用了cal.clear()。 ),这将导致日历中的属性值更改为初始值。如果有多个线程并发,有可能线程A刚刚执行了create方法,而线程B执行了cal.clear(),导致最终解析。异常。
面试官:由于SimpleDateFormat类中的日历是共享变量,因此可以将SimpleDateFormat类型变量设置为方法私有。你可以每次想用的时候就换一个新的,也可以使用同步锁来控制并发访问。为什么用ThreadLocal那么麻烦呢?
小白:方法私有性和同步锁并发控制确实可以解决问题,但是它们也有各自的缺点。方法是私有的,每次都需要创建一个新的对象,不仅占用内存,还需要不断回收。同步锁并发控制,在多线程并发量较高的情况下,性能会严重下降。使用ThreadLocal封装,每个线程只需要创建一个SimpleDateFormat对象实例,既解决了不断创建新对象的问题,又解决了并发问题。
面试官:那你为什么在你一开始写的代码的finally方法中使用了df.remove()呢?这是为什么呢?
小白:线程已经用完了SimpleDateFormat。如果不调用remove方法清除的话,可能会导致使用ThreadLocal导致的内存泄漏。
原创文章,作者:小su,如若转载,请注明出处:https://www.sudun.com/ask/113651.html
用户评论
回到你身边
这个标题戳中了我的心啊!我面试的时候也碰到过这个问题,面试官就给我一堆“为什么SimpleDateFormat不是线程安全的”的问题绕来绕去,我都答不下去了…
有9位网友表示赞同!
早不爱了
我觉得总结得真好,每次面试都遇到一些类似的套路问题,要好好记住这些知识点,下次考试和面试再也不怕了!面试的时候要注意心态,别被问懵了。
有17位网友表示赞同!
微信名字
看完这篇文章,我突然明白以前为什么那些Java线程安全的问题总是搞不明白。SimpleDateFormat不是线程安全的原理确实有点绕,不过文章讲解得非常清楚,建议平时多学习一些相关的知识点,这样面试的时候就不会措手不及。
有6位网友表示赞同!
南宫沐风
每次面试都被这些套路问题问烦了!这个标题简直太贴切了,你讲得一点都没错,SimpleDateFormat不安全是因为内部的解析和格式化操作并非原子性,多个线程同时访问会产生数据竞争的情况…
有10位网友表示赞同!
不相忘
这篇文章真是太棒了!我最近在学习Java并发编程,就遇到过SimpleDateFormat的问题。原来是这么个原理啊,要好好记住了,下次面试就不会被问得一头雾水了。
有13位网友表示赞同!
你tm的滚
面试官这些套路问题也忒难答了,感觉好像要把你逼到不行似的,哎!这种技巧性的面试问题还是少碰的好吧!
有10位网友表示赞同!
几妆痕
感觉这篇文章很实用啊!尤其说SimpleDateFormat的线程不安全问题,之前遇到过几次类似的场景。要记得学习其他的安全替代方案,比如使用Date/Time API。
有6位网友表示赞同!
蝶恋花╮
这篇文章让我学到了很多知识点,面试官总是喜欢用一些看似刁难的问题来考察你的底蕴,建议大家平时多关注Java并发编程的安全问题,这样才能应付各种面试的挑战!
有18位网友表示赞同!
青衫故人
之前面试的时候也遇到过SimpleDateFormat的相关问题,当时完全答不上来…看来需要好好学习一下这些知识点,下次再也不敢轻敌了!
有15位网友表示赞同!
冷眼旁观i
面试官真是太牛了!都能把这种看似简单的技术问题问得这么深层次,佩服佩服~这篇文章总结得真好,以后面试的时候遇到类似的问题也能快速应对。
有5位网友表示赞同!
为爱放弃
这篇文章对我来说很有帮助!之前一直在学习Java线程安全相关的知识,但是始终不知道SimpleDateFormat为什么不安全…原来是内部的解析和格式化操作不是原子性的原因。
有13位网友表示赞同!
傲世九天
我觉得文章还是挺不错的,只是有些地方表达得比较生硬,可以考虑用更通俗易懂的语言描述一下问题,这样对一些新手小白来说会更容易理解。
有12位网友表示赞同!
荒野情趣
面试官套路题就太恶心了!每次问的问题都感觉跟没完一样!而且那些理论性的知识点也记不清多少,希望以后能遇到一些实际操作技能类型的题目…
有9位网友表示赞同!
秒淘你心窝
这篇文章让我觉得Java并发编程可真复杂啊! 虽然说SimpleDateFormat不安全是因为内部的解析和格式化操作并非原子性,能够导致数据竞争问题,但具体如何避免这种情况,还有待深入学习。
有17位网友表示赞同!
余笙南吟
我觉得文章说的没错,面试官这些套路问答就是为了考察你的解题思路和应对能力! 不管是啥类型的问题,都要保持冷静思绪,仔细分析后再进行回答。
有6位网友表示赞同!
淡淡の清香
这篇文章让我受益良多,原来SimpleDateFormat不安全的根本原因在于其内部的解析和格式化操作不是原子性操作!太重要了,面试中真的要提前做好了解和准备!
有20位网友表示赞同!
猫腻
面试官喜欢用这类套路问题来考察你的Java基础知识,一定要把这些重点梳理清楚,下次面试就不会被问懵了!
有14位网友表示赞同!