当前位置: 首页 > article >正文

DateFormat使用时需要注意:多线程下需要特殊处理

前言

工作或学习过程中难免会接触到时间(Date)相关的内容,比如String类型转为Date类型,或者Date类型转为String类型,jdk为我们提供了一套完善的日期格式化工具,DateFormat类,使用者可以使用该接口实现常用日期的格式化。但是这里面有个坑…

DateFormat使用

package com.cz.threadLocal;

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

/**
 * @program: Reids
 * @description:
 * @author: Cheng Zhi
 * @create: 2023-04-27 20:13
 **/
public class TestSimpleDataFormat {

    private static class DateUtils {

        private static DateFormat dateFormat = new SimpleDateFormat("yyyymmdd");

        public static Date strToDate(String strDate) {
            try {
                Date yyyymmdd = dateFormat.parse(strDate);
                return yyyymmdd;
            } catch (ParseException e) {
                e.printStackTrace();
            }

            return null;
        }
    }

    public static void main(String[] args) {
        //System.out.println(DateUtils.strToDate("20230111"));

        for (int i=0; i<5; i++) {
            final int ii = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(DateUtils.strToDate("2023011" + ii));
                }
            }).start();
        }
    }
}

以上就是一个日期转换的测试类,但是实际运行起来会报错,如下:

image.png

原因是什么呢?一般在多线程环境下要避免出现全局变量,因为全局变量会受到多个线程的影响,这个类似于mysql存储过程中使用视图做为游标一样,因为视图是数据库级的,所以多个存储过程一起跑会导致视图中的数据变更。java中也是一样的,全局变量会被各个线程去读取或修改。就上面的例子而言,这里有多处问题:
1、private static DateFormat dateFormat = new SimpleDateFormat(“yyyymmdd”); 使用static修饰,这个就相当于多个线程会共享,所以这里本身就是不安全的。
2、SimpleDateFormat这个类本身就是不安全的,如下:

image.png

该类中使用了全局变量。

image.png

CalendarBuilder中存在有一个establish方法,在执行该方法时,会将全局变量中的内容清除(这里使用的是逻辑清除,即全部设置为0),所以多个线程下,如果线程A清除了stamp[]中的内容,线程B要使用stamp[]中的内容,这里就会产生异常。

因此在多线程中使用DateFormat时要考虑线程安全问题,既然说到线程安全,那一般就有如下几个方法:
1、每次使用new 一个新的对象,但是这样效率很低。
2、在使用DateFormat的时候,加锁。
3、将DateFormat对象使用ThreadLocal来存储。
修改后的代码如下:

package com.cz.threadLocal;

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

/**
 * @program: Reids
 * @description:
 * @author: Cheng Zhi
 * @create: 2023-04-27 20:13
 **/
public class TestSimpleDataFormat {

    private static class DateUtils {

        private static ThreadLocal<DateFormat> dateFormatThreadLocal = new ThreadLocal<DateFormat>() {
            @Override
            protected DateFormat initialValue() {
                DateFormat dateFormat = new SimpleDateFormat("yyyymmdd");
                return dateFormat;
            }
        };

        public static Date strToDate(String strDate) {
            try {
                Date yyyymmdd = dateFormatThreadLocal.get().parse(strDate);
                return yyyymmdd;
            } catch (ParseException e) {
                e.printStackTrace();
            }

            return null;
        }
    }

    public static void main(String[] args) {
        //System.out.println(DateUtils.strToDate("20230111"));

        for (int i=0; i<5; i++) {
            final int ii = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(DateUtils.strToDate("2023011" + ii));
                }
            }).start();
        }
    }
}

运行效果:

image.png


http://www.kler.cn/a/15955.html

相关文章:

  • git常用命令+搭vscode使用
  • More effective C++:杂项
  • 密码学在网络安全中的应用
  • Excel模板下载\数据导出
  • ubuntu 22.04 shell
  • 黑马嵌入式开发入门模电基础学习笔记
  • NTT入门 开拓者的卓识
  • Pycharm卡顿、反应慢、CPU占用高
  • 嘉明的数据结构学习Day5——作栈和队列以及它们的顺序存储与链式存储的实现
  • D触发器仿真实验
  • 【高危】泛微 e-cology <10.57 存在 SQL注入漏洞(POC)(MPS-ndqt-0im5)
  • SVG中line标签的使用以及其外观属性的运用
  • 小程序获取input的值,以及绑定输入事件
  • 使用物联网技术进行肥胖管理是可行的吗?
  • 第四十四章 管理镜像 - 传入日记传输率
  • 配置 RT-Thread 的工程目录
  • 【14.HTML-移动端适配】
  • 人工智能技术在建筑能源管理中的应用场景
  • AI绘画——Lora模型Niji-Expressive V2 launch(灵动优雅,张力尽显)
  • LabVIEW CompactRIO 开发指南 3 选择CompactRIO编程模式
  • 架构基本概念和架构本质
  • 这年头,谁还在「贩卖」生活方式?
  • 【python知识】运算符博览
  • css 实现太极效果
  • 【MFAC】基于紧格式动态线性化的无模型自适应控制
  • Redis知识点