zoukankan      html  css  js  c++  java
  • 《java多线程编程核心技术》----simpleDateFormat非线程安全

    类simpleDateFormat主要负责日期的转换和格式化,但在多线程的环境中,使用此内容容易造成数据转换以及处理的不准确,

    因为simpleDateFormat类并不是线程安全的。

    public class MyThread extends Thread {
    
        private SimpleDateFormat sdf;
        private String dateString;
    
        public MyThread(SimpleDateFormat sdf, String dateString) {
            super();
            this.sdf = sdf;
            this.dateString = dateString;
        }
    
        @Override
        public void run() {
            try {
                // dateString 传入的日期字符串
                Date dateRef = sdf.parse(dateString);
                // newDateString 根据传入的字符串转换成日期,然后,在转换后的字符串
                String newDateString= sdf.format(dateRef).toString();
                if(!newDateString.equals(dateString)){
                    System.out.println("ThreadName="+this.getName()
                    +"报错了 日期字符串:"+dateString+" 转换成的日期为:"+newDateString);
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
    }

    测试,以及结果

    public class Test {
    
        public static void main(String[] args) {
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
            String[] dateStringArray=new String[]{
                    "2001-01-01","2000-01-02","2000-01-03",
                    "2001-01-04","2000-01-05","2000-01-06",
                    "2001-01-07","2000-01-08","2000-01-09","2000-01-10"
            };
    
            MyThread[] threadArray=new MyThread[10];
            for (int i = 0; i < 10; i++) {
                threadArray[i]=new MyThread(sdf,dateStringArray[i]);
            }
            for (int i = 0; i < 10; i++) {
                threadArray[i].start();
            }
        }
    }
    
    ThreadName=Thread-1报错了 日期字符串:2000-01-02 转换成的日期为:1970-01-01
    ThreadName=Thread-4报错了 日期字符串:2000-01-05 转换成的日期为:1970-01-01
    ThreadName=Thread-3报错了 日期字符串:2001-01-04 转换成的日期为:1970-01-01
    ThreadName=Thread-2报错了 日期字符串:2000-01-03 转换成的日期为:2000-01-01

    使用单例的simpleDateFormat类在多线程的环境中处理,容易出错。

    解决方法一

    public class DateTools {
    
        // 经过字符串转换成指定格式的日期
        public static Date parse(String formatPattern, String dateString) throws ParseException {
            return new SimpleDateFormat(formatPattern).parse(dateString);
        }
    
        // 将日期转换成指定的格式的字符串
        public static String format(String formatPattern,Date date) {
            return new SimpleDateFormat(formatPattern).format(date).toString();
        }
    }
    public class MyThread extends Thread {
    
        private SimpleDateFormat sdf;
        private String dateString;
    
        public MyThread(SimpleDateFormat sdf, String dateString) {
            super();
            this.sdf = sdf;
            this.dateString = dateString;
        }
    
        @Override
        public void run() {
            try {
                // dateString 传入的日期字符串
                Date dateRef = DateTools.parse("yyyy-MM-dd",dateString);
                // newDateString 根据传入的字符串转换成日期,然后,在转换后的字符串
                String newDateString= DateTools.format("yyyy-MM-dd",dateRef);
                if(!newDateString.equals(dateString)){
                    System.out.println("ThreadName="+this.getName()
                    +"报错了 日期字符串:"+dateString+" 转换成的日期为:"+newDateString);
                }else{
                    System.out.println("ThreadName="+this.getName()
                            +" 日期字符串:"+dateString+" 转换成的日期为:"+newDateString);
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
    
    }

    没有任何异常,解决处理错误的原理其实就是创建多个simpleDateFormat类的实例;

    解决方法二

    threadlocal类能使线程绑定到指定的对象。

    public class DateTools {
    
        // ThreadLocal相当于一个map,key为线程的标识,value为每个线程设置的value
        private static ThreadLocal<SimpleDateFormat> t1 = new ThreadLocal<>();
    
        public static SimpleDateFormat getSimpleDateFormat(String datePattern) {
            SimpleDateFormat sdf = null;
            sdf = t1.get();
            if (sdf == null) {
                sdf = new SimpleDateFormat(datePattern);
                t1.set(sdf);
            }
            return sdf;
        }
    }
    public class MyThread extends Thread {
    
        private SimpleDateFormat sdf;
        private String dateString;
    
        public MyThread(SimpleDateFormat sdf, String dateString) {
            super();
            this.sdf = sdf;
            this.dateString = dateString;
        }
    
        @Override
        public void run() {
            try {
                // dateString 传入的日期字符串
                Date dateRef = DateTools.getSimpleDateFormat("yyyy-MM-dd").parse(dateString);
                // newDateString 根据传入的字符串转换成日期,然后,在转换后的字符串
                String newDateString= DateTools.getSimpleDateFormat("yyyy-MM-dd").format(dateRef).toString();
                if(!newDateString.equals(dateString)){
                    System.out.println("ThreadName="+this.getName()
                    +"报错了 日期字符串:"+dateString+" 转换成的日期为:"+newDateString);
                }else{
                    System.out.println("ThreadName="+this.getName()
                            +" 日期字符串:"+dateString+" 转换成的日期为:"+newDateString);
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
    
    }
    

      这种结果没有异常。

  • 相关阅读:
    第七次作业-话费充值
    第七次作业-qq登录&跳转
    第六次作业
    第五次作业
    第四次作业
    jsp第二次作业
    第一次jsp作业
    第九次作业
    第八次作业
    第七次2作业
  • 原文地址:https://www.cnblogs.com/windy13/p/11336384.html
Copyright © 2011-2022 走看看