文档章节

SimpleDateFormat 线程不安全的

p
 piz__
发布于 2017/02/04 15:22
字数 460
阅读 40
收藏 1

原因

由源码可以知道,SimpleDateFormat 类的数据时保存在类中的,如果我们在自己的类开始就声明public static final SimpleDateFormat SDF = new SimpleDateFormat("MMdd");的话,那么SimpleDateFormat 内部数据就会混乱。出现日期转换错误。

测试

使用单元测试,在多线程中对两个日期操作,当只剩下最后一个线程的时候,错误不会再出现。

package com.ch.dcs.sync.core.test;

import org.junit.Test;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Created by 002387 on 2017/2/3.
 */
public class DateFormatTest {
    public static final SimpleDateFormat SDF = new SimpleDateFormat("MMdd");

    @Test
    public void test1(){
        Calendar c = Calendar.getInstance();
        Date d1 = c.getTime();
        c.add(Calendar.DATE, -3);
        Date d2 = c.getTime();
        final String s1 = SDF.format(d1);
        final String s2 = SDF.format(d2);
        System.out.println(String.format("test date %s and %s", s1, s2));
        final Random ran = new Random();

        final AtomicLong count = new AtomicLong(0);
        for (int i = 0; i < 3; i++) {
            new Thread() {
                @Override
                public void run() {
                    for (;;) {
                        count.addAndGet(1);
                        boolean flag = ran.nextBoolean();
                        Date d = flag ? d1 : d2;
                        String s = flag ? s1 : s2;
                        String r = SDF.format(d);
                        if(!s.equals(r)){
                            System.out.println(String.format("== count %s date %s format to %s", count.get(), d.toString(), r));
                            throw new RuntimeException("");
                        } else {
        //                     System.out.println(String.format("thread %s date %s format to %s", Thread.currentThread(), d.toString(), r));
                        }
                    }
                }
            }.start();

        }

        try {
            Thread.sleep(Long.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

会抛出RuntimeException异常,当线程数只剩下一的时候,异常消失,同时数据也不会出现错误, 结果:

test date 0203 and 0131
== count 21 date Fri Feb 03 16:16:12 CST 2017 format to 0231
== count 50 date Fri Feb 03 16:16:12 CST 2017 format to 0231
Exception in thread "Thread-0" java.lang.RuntimeException: 
	at com.ch.dcs.sync.core.test.DateFormatTest$1.run(DateFormatTest.java:41)
Exception in thread "Thread-2" java.lang.RuntimeException: 
	at com.ch.dcs.sync.core.test.DateFormatTest$1.run(DateFormatTest.java:41)

Process finished with exit code 1

###解决办法

1.使用局部变量,每个线程中声明自己的对象,但是消耗太大,不可取。 2.使用 ThreadLocal,这里每个线程将有它自己的 SimpleDateFormat 副本。

private static final ThreadLocal<DateFormat> FORMAT = new ThreadLocal<DateFormat>(){
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMddHHmmss");
        }
    };
//获取对象的时候使用get()方法如下
ORMAT.get().parse("20161010000000");

3.使用同步锁

© 著作权归作者所有

p
粉丝 4
博文 28
码字总数 15580
作品 0
上海
私信 提问
Java并发编程笔记之SimpleDateFormat源码分析

SimpleDateFormat 是 Java 提供的一个格式化和解析日期的工具类,日常开发中应该经常会用到,但是由于它是线程不安全的,多线程公用一个 SimpleDateFormat 实例对日期进行解析或者格式化会导...

狂小白
2018/07/12
0
0
线程不安全的SimpleDateFormat

8.5 SimpleDateFormat是线程不安全的 SimpleDateFormat是Java提供的一个格式化和解析日期的工具类,日常开发中应该经常会用到,但是由于它是线程不安全的,多线程公用一个SimpleDateFormat实...

今天你不奋斗明天你就落后
2017/12/14
0
0
Java并发编程之SimpleDateFormat源码分析

SimpleDateFormat 是 Java 提供的一个格式化和解析日期的工具类,日常开发中应该经常会用到,但是由于它是线程不安全的,多线程公用一个 SimpleDateFormat 实例对日期进行解析或者格式化会导...

狂小白
2018/07/12
0
0
Java 线程不安全的SimpleDateFormat

SimpleDateFormat是Java提供的一个格式化和解析日期的工具类 但是由于它是线程不安全的,多线程共用一个SimpleDateFormat实例对日期进行解析或者格式化会导致程序出错 问题重现 public class...

晨猫
2018/01/31
0
0
java并发编程——线程不安全的类

什么是线程不安全的类? 如果一个类的对象同时被多个线程访问,如果不做特殊的同步或并发处理,很容易表现出线程不安全的现象,比如抛出异常、逻辑处理错误等,这种类我们就称为线程不安全的...

长头发-dawn
2018/10/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

好文:华杉:我等用功,不求日增,但求日减。减一分人欲,则增一分天理,这是何等简易!何等洒脱!

华杉华与华营销咨询公司董事长 华杉 做企业就得遵守三大定律 今天我给大家带来的这个题目比较大,叫做《企业三大定律》。 首先我们得明白定律是什么? 定律在英文里面叫law,定律就是法律。做...

阿锋zxf
14分钟前
1
0
vue 的bus总线

bus声明 global.bus = new Vue() 事件发送 controlTabbar () {global.bus.$emit('pickUp', 'ddd')}, 事件接收 global.bus.$on('pickUp', (res) => {this.isFocus = true})......

Js_Mei
19分钟前
2
0
大型系统演进之路-负载均衡演进

Nginx做负载均衡 通过Nginx的反向代理将请求分发到tomcat中,如果tomcat支持100并发,Nginx支持50000并发,理论上nginx把请求发送到500个tomcat就可以了。 LVS或F5做多个Nginx负载均衡 Tomc...

春哥大魔王的博客
24分钟前
4
0
Sqlite时间段查询中遇到的问题

问题: 我要查询DateTime时间其中的一段符合时间要求的数据,比如我要查询‘2019-06-06 16:50:00’至‘2019-06-06 16:59:00’这一段的数据 开始用这段代码 strSql= ("select * from Coll...

rainbowcode
27分钟前
2
0
大数据(hadoop-数据入库系统Sqoop原理架构)

Sqoop是什么 Sqoop:SQL-to-Hadoop 连接传统关系型数据库和Hadoop的桥梁 把关系型数据库的数据导入到 Hadoop 系统 ( 如 HDFS、HBase 和 Hive) 中; 把数据从 Hadoop 系统里抽取并导出到关系型...

这很耳东先生
42分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部