面试官一步步教你为什么SimpleDateFormat不是线程安全的

面试官:SimpleDateFormat用过吗?小小白:用过,用来格式化或解析日期时间。面试官:能写一下你是如何使用的吗?小小白:噼里啪啦敲完了,代码如下:pu

今天给各位分享面试官一步步教你为什么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=区域设置;

面试官一步步教你为什么SimpleDateFormat不是线程安全的

初始化(语言环境);

}

//如果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导致的内存泄漏。

用户评论

面试官一步步教你为什么SimpleDateFormat不是线程安全的
回到你身边

这个标题戳中了我的心啊!我面试的时候也碰到过这个问题,面试官就给我一堆“为什么SimpleDateFormat不是线程安全的”的问题绕来绕去,我都答不下去了…

    有9位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
早不爱了

我觉得总结得真好,每次面试都遇到一些类似的套路问题,要好好记住这些知识点,下次考试和面试再也不怕了!面试的时候要注意心态,别被问懵了。

    有17位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
微信名字

看完这篇文章,我突然明白以前为什么那些Java线程安全的问题总是搞不明白。SimpleDateFormat不是线程安全的原理确实有点绕,不过文章讲解得非常清楚,建议平时多学习一些相关的知识点,这样面试的时候就不会措手不及。

    有6位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
南宫沐风

每次面试都被这些套路问题问烦了!这个标题简直太贴切了,你讲得一点都没错,SimpleDateFormat不安全是因为内部的解析和格式化操作并非原子性,多个线程同时访问会产生数据竞争的情况…

    有10位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
不相忘

这篇文章真是太棒了!我最近在学习Java并发编程,就遇到过SimpleDateFormat的问题。原来是这么个原理啊,要好好记住了,下次面试就不会被问得一头雾水了。

    有13位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
你tm的滚

面试官这些套路问题也忒难答了,感觉好像要把你逼到不行似的,哎!这种技巧性的面试问题还是少碰的好吧!

    有10位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
几妆痕

感觉这篇文章很实用啊!尤其说SimpleDateFormat的线程不安全问题,之前遇到过几次类似的场景。要记得学习其他的安全替代方案,比如使用Date/Time API。

    有6位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
蝶恋花╮

这篇文章让我学到了很多知识点,面试官总是喜欢用一些看似刁难的问题来考察你的底蕴,建议大家平时多关注Java并发编程的安全问题,这样才能应付各种面试的挑战!

    有18位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
青衫故人

之前面试的时候也遇到过SimpleDateFormat的相关问题,当时完全答不上来…看来需要好好学习一下这些知识点,下次再也不敢轻敌了!

    有15位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
冷眼旁观i

面试官真是太牛了!都能把这种看似简单的技术问题问得这么深层次,佩服佩服~这篇文章总结得真好,以后面试的时候遇到类似的问题也能快速应对。

    有5位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
为爱放弃

这篇文章对我来说很有帮助!之前一直在学习Java线程安全相关的知识,但是始终不知道SimpleDateFormat为什么不安全…原来是内部的解析和格式化操作不是原子性的原因。

    有13位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
傲世九天

我觉得文章还是挺不错的,只是有些地方表达得比较生硬,可以考虑用更通俗易懂的语言描述一下问题,这样对一些新手小白来说会更容易理解。

    有12位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
荒野情趣

面试官套路题就太恶心了!每次问的问题都感觉跟没完一样!而且那些理论性的知识点也记不清多少,希望以后能遇到一些实际操作技能类型的题目…

    有9位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
秒淘你心窝

这篇文章让我觉得Java并发编程可真复杂啊! 虽然说SimpleDateFormat不安全是因为内部的解析和格式化操作并非原子性,能够导致数据竞争问题,但具体如何避免这种情况,还有待深入学习。

    有17位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
余笙南吟

我觉得文章说的没错,面试官这些套路问答就是为了考察你的解题思路和应对能力! 不管是啥类型的问题,都要保持冷静思绪,仔细分析后再进行回答。

    有6位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
淡淡の清香

这篇文章让我受益良多,原来SimpleDateFormat不安全的根本原因在于其内部的解析和格式化操作不是原子性操作!太重要了,面试中真的要提前做好了解和准备!

    有20位网友表示赞同!

面试官一步步教你为什么SimpleDateFormat不是线程安全的
猫腻

面试官喜欢用这类套路问题来考察你的Java基础知识,一定要把这些重点梳理清楚,下次面试就不会被问懵了!

    有14位网友表示赞同!

原创文章,作者:小su,如若转载,请注明出处:https://www.sudun.com/ask/113651.html

(0)
小su's avatar小su
上一篇 2024年9月1日 上午12:52
下一篇 2024年9月1日 上午12:57

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注