为什么SimpleDateFormat线程不安全?

SimpleDateFormat中有个属性calendar(protected Calendar calendar;)继承自DataFormat, 所以当不同的线程如果用的是同一个SimpleDateFormat对象,则calendar对象也是完全相同的内存;

SimpleDateFormat的format方法中将传入的时间date set给了calendar属性(calendar.setTime(date););

当A线程传入时间a调用format方法进行格式化,format方法还没执行完,此时B线程传入时间b调用format方法进行格式化,则A线程中的calendar的time就变成了B线程传入的时间b了,当执行format方法中的subFormat方法时,获取calendar中的时间就线程不安全了。

java.text.SimpleDateFormat#format(java.util.Date, java.lang.StringBuffer, java.text.Format.FieldDelegate)源码如下:

private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate) {
// Convert input date to time field list
calendar.setTime(date); boolean useDateFormatSymbols = useDateFormatSymbols(); for (int i = 0; i < compiledPattern.length; ) {
// 省略部分代码……
switch (tag) {
case TAG_QUOTE_ASCII_CHAR:
toAppendTo.append((char)count);
break; case TAG_QUOTE_CHARS:
toAppendTo.append(compiledPattern, i, count);
i += count;
break; default:
subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
break;
}
}
return toAppendTo;
}

java.text.SimpleDateFormat#subFormat 源码:

private void subFormat(int patternCharIndex, int count,
FieldDelegate delegate, StringBuffer buffer,
boolean useDateFormatSymbols)
{
int maxIntCount = Integer.MAX_VALUE;
String current = null;
int beginOffset = buffer.length(); int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
int value;
if (field == CalendarBuilder.WEEK_YEAR) {
if (calendar.isWeekDateSupported()) {
value = calendar.getWeekYear();
} else {
// use calendar year 'y' instead
patternCharIndex = PATTERN_YEAR;
field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
value = calendar.get(field);
}
} else if (field == CalendarBuilder.ISO_DAY_OF_WEEK) {
value = CalendarBuilder.toISODayOfWeek(calendar.get(Calendar.DAY_OF_WEEK));
}
// 省略部分代码……

解决方法

  1. 不同线程使用不同的SimpleDateFormat对象,每次new一个新的出来或者使用ThreadLocal,缺点消耗内存资源
  2. 要执行SimpleDateFormat之前进行加锁,缺点效率不高
  3. 使用其他时间类比如Java8线程安全的DateTimeFormatter,缺点可能是要重构老代码等

为什么SimpleDateFormat线程不安全?的更多相关文章

  1. SimpleDateFormat线程不安全及解决办法

    原文链接:https://blog.csdn.net/csdn_ds/article/details/72984646 以前没有注意到SimpleDateFormat线程不安全的问题,写时间工具类,一 ...

  2. SimpleDateFormat线程不安全及解决办法(转)

    以前没有注意到SimpleDateFormat线程不安全的问题,写时间工具类,一般写成静态的成员变量,不知,此种写法的危险性!在此讨论一下SimpleDateFormat线程不安全问题,以及解决方法. ...

  3. SimpleDateFormat线程不安全原因及解决方案

    一. 线程不安全验证: /** * SimpleDateFormat线程安全测试 * 〈功能详细描述〉 * * @author 17090889 * @see [相关类/方法](可选) * @sinc ...

  4. SimpleDateFormat线程不安全的5种解决方案!

    1.什么是线程不安全? 线程不安全也叫非线程安全,是指多线程执行中,程序的执行结果和预期的结果不符的情况就叫做线程不安全. ​ 线程不安全的代码 SimpleDateFormat 就是一个典型的线程不 ...

  5. SimpleDateFormat线程不安全问题处理

    在工作中,通过SimpleDateFormat将字符串类型转为日期类型时,发现有时返回的日期类型出错,调用方法如下: public final class DateUtil { static fina ...

  6. SimpleDateFormat 线程不安全及解决方案

    SimpleDateFormat定义 SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类.它允许进行格式化(日期 -> 文本).解析(文本 -> 日期 ...

  7. SimpleDateFormat线程不安全及解决的方法

    一. 为什么SimpleDateFormat不是线程安全的? Java源代码例如以下: /** * Date formats are not synchronized. * It is recomme ...

  8. SimpleDateFormat线程不安全(转)

    有三种方法可以解决以上安全问题.  1).使用同步 package com.bijian.study.date; import java.text.ParseException; import jav ...

  9. 解决SimpleDateFormat线程安全问题

    package com.tanlu.user.util; import java.text.DateFormat; import java.text.ParseException; import ja ...

  10. SimpleDateFormat线程不安全问题解决及替换方法

    场景:在多线程情况下为避免多次创建SimpleDateForma实力占用资源,将SimpleDateForma对象设置为static. 出现错误:SimpleDateFormat定义为静态变量,那么多 ...

随机推荐

  1. 用 Proxy 进一步提高 npm 安装速度

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  2. Flutter对于移动端软件跨平台后台保活的技术浅析

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 18px; o ...

  3. .NET 8 开发的跨平台多商户第三方支付SDK

    前言 快速发展的互联网应用开发中,支付功能已成为各类平台不可或缺的一环.为了帮助大家更高效地接入主流支付渠道,推荐一套基于 .NET 开发的第三方支付 SDK.该 SDK 支持跨平台运行,适用于多种操 ...

  4. 使用PocketFlowSharp创建一个Human_Evaluation示例

    效果 实践 有时候AI生成的结果我们并不满意在进入下一步之前,我们需要对AI生成的结果进行人工审核,同意了才能进入下一个流程. Human_Evaluation就是人工判断的一个简单示例. inter ...

  5. 网络编程:epoll

    原理 select 的几个缺点: 1)每次调用select,都需要把fd集合从用户空间拷贝到内核空间,这个开销在fd很多时会很大 2)每次调用select都需要在内核遍历传递进来的所有fd,这个开销在 ...

  6. 京东首页html+css1.0

    小菜鸟的学习记录,还望各位猿兄不吝赐教 文章目录 效果图 源码 HTML文件 css文件 效果图 源码 HTML文件 <!DOCTYPE html> <html> <he ...

  7. windows安装node.js加配置淘宝镜像

    下载:https://nodejs.org/en/download/ 一路默认,或者选自己的路径,装好后打开cmd, 输入 node --version 显示版本. 是的,环境自己就配置好了! 配置淘 ...

  8. 玩转C++11多线程:让你的程序飞起来的std::thread终极指南

    大家好,我是小康. 你还在为 C++ 多线程编程发愁吗?别担心,今天咱们就用大白话彻底搞定std::thread!看完这篇,保证你对C++11多线程的理解从"一脸懵逼"变成&quo ...

  9. 把多个文件打包压缩成tar.gz文件并解压的Java实现

    压缩文件   在Java中,可以 使用GZIPOutputStream创建gzip(gz)压缩文件,它在commons-compress下面,可以通过如下的maven坐标引入: <depende ...

  10. 记一道有趣的交互题 noi.ac #2035歪比巴卜

    记一道有趣的交互题 noi.ac #2035歪比巴卜 Problem Alice手上有两个\(\le n\)且不同的正整数\(x,y\),Bob手上有一个正整数\(z\),已经确认是\(x\)或\(y ...