DateFormat的format()方法线程不安全的问题分析

最近看到《侦探剧场:堆内存神秘溢出事件》https://my.oschina.net/u/2368090/blog/1628720,于是自己也想测试了解一下DateFormat的多线程安全问题。

首先先看现象:做一个多线程使用同一个SimplyDateFormat的测试例子:

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFormatTest {

    static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    public static void main(String[] args) throws Exception{

        Date start = sdf.parse("2018-03-01");
        Date end = sdf.parse("2018-03-03");

        final Date other =sdf.parse("2018-03-07");
        for(int i=0; i<100; i++) {
            new Thread(new Runnable() {
                public void run() {
                    sdf.format(other);
                }
            }).start();
        }

        System.out.println("start:" + sdf.format(start));
        System.out.println("end:" + sdf.format(end));
    }

}

(这段代码在虚拟机能很快重现问题,在Mac上要迅速不断点击运行才会重现--)

预期结果:

出现线程安全的结果:

现象看完之后找原因:

1.DateFormat(父类)定义了一个全局的Calendar:

SimplyDateFormat的format()方法在线程不安全的情况下使用了全局的calendar:

产生问题的大致运行顺序也许是这样的:

原文地址:https://www.cnblogs.com/cici20166/p/8525563.html

时间: 2024-08-29 15:00:42

DateFormat的format()方法线程不安全的问题分析的相关文章

.NET String.Format 方法 线程安全问题

碰到这个问题 是在和淘宝做信息交互的时候, 接收别人N年前的代码. 代码逻辑很简单,就是取得信息 数据库查询  响应请求返回结果. 最近淘宝的人反映说 N多账户使用的是一个单号.理论上来说 是应该每次都不一样的. 最坑爹的是还出现了 数据库中没数据 但是响应结果却有数据了的神奇现象! 反编译代码,整理后发现 逻辑很简单. 尼玛 问题找不到怎么办???!! 第二个反映就是 可能出现并发了. 一行一行的排查可能出现的并发的地方. 最后发现  String.Format 很有肯能 . 百度后发现 全都

String.format()方法使用说明

JDK1.5开始String类中提供了一个非常有用的方法String.format(String format, Object ... args) 查看源码得知其实是调用了Java.util.Formatter.format(String, Object...)方法 [java] view plain copy print? public static String format(String format, Object ... args) { return new Formatter().f

java采用DateFormat日期格式化方法判断用户今天是否第一次登录(比较简单)

一.描述 1.数据库中有一个date类型的last_login_time字段,即用户每次登录都会更新该字段: 2.在登录时使用jdbcTemplate的queryForObject方法,取出last_login_time字段的值以Date类型返回,并用DateFormat格式化该时间 3.获取系统当前时间,并用DateFormat格式化,比较两个时间是否相等就可以判断该用户今天是否第一次登录. 上次我写的判断用户当天是否第一次登录的方法采用字符串的比较方式,使用起来很繁琐,效率也不高,因此今天进

java基础----&gt;String和MessageFormat的format方法

这里介绍一下String和MessageFormat中的format方法的差异以及实现原理. String与MessageFormat的说明 一.两者的使用场景 String.format:for layout justification and alignment, common formats for numeric, string, and date/time data, and locale-specific output. MessageFormat.format:to produce

测试String.Format方法

今天想使用String.Format,和平时的用法不一样. 直接上代码: [Test] public void TestMethod6() { string A = "A"; string B = "B"; string C = "C"; string D = "{0}"; String str = String.Format(D, A, B, C); Assert.AreEqual(str, "A");

C#语言基础知识(4):C#中的String.Format方法

定义String.Format是将指定的String类型的数据中的每个格式项替换为相应对象的值的文本等效项.(1)string p1="xiaomeng";string p2="xiaobei";Response.Write(String.Format("Hello {0},I'm {1}",p1,p1));(2)Response.Write(String.Format("Hello {0},I'm {1}","xi

前段 format方法

a.为字符串创建format方法,用于字符串格式化 String.prototype.format=function (arg) { //console.log(this,arg); //this,当前调用方法的字符串,arg为Format方法传入的参数 //return '666'; //return,格式化之后获取的新内容,return啥就替换为啥 var temp = this.replace(/\{(\w+)\}/g,function (k,kk) { // k相当于{(\w+)},kk

python的str.format方法

format方法被用于字符串的格式化输出. print('{0}+{1}={2}'.format(1,2,1+2)) #in 1+2=3 #out 可见字符串中大括号内的数字分别对应着format的几个参数. 若省略数字: print('{}+{}={}'.format(1,2,1+2)) #in 可以得到同样的输出结果.但是替换顺序默认按照[0],[1],[2]...进行. 若替换{0}和{1}: print('{1}+{0}={2}'.format(1,2,1+2)) #in 2+1=3 #

实现Date函数属性中的format方法

js中没有Date.format方法的,所以在date属性中加format方法 //js格式化属性 Date.prototype.format = function (format) { var o = { "M+": this.getMonth() + 1, //month "d+": this.getDate(), //day "h+": this.getHours(), //hour "m+": this.getMinu