龙空技术网

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

马士兵老师 509

前言:

此刻看官们对“dateformatjava”大约比较重视,我们都想要知道一些“dateformatjava”的相关资讯。那么小编在网上收集了一些关于“dateformatjava””的相关内容,希望同学们能喜欢,我们一起来了解一下吧!

前言

工作或学习过程中难免会接触到时间(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();        }    }}

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

原因是什么呢?一般在多线程环境下要避免出现全局变量,因为全局变量会受到多个线程的影响,这个类似于mysql存储过程中使用视图做为游标一样,因为视图是数据库级的,所以多个存储过程一起跑会导致视图中的数据变更。java中也是一样的,全局变量会被各个线程去读取或修改。就上面的例子而言,这里有多处问题:

1、private static DateFormat dateFormat = new SimpleDateFormat("yyyymmdd"); 使用static修饰,这个就相当于多个线程会共享,所以这里本身就是不安全的。

2、SimpleDateFormat这个类本身就是不安全的,如下:

该类中使用了全局变量。

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();        }    }}

运行效果:

原文链接:

标签: #dateformatjava #oracle内部date格式化 #mysqldatestring