zoukankan      html  css  js  c++  java
  • 非线程安全的类-SimpleDateFormat

    类SimpleDateFormat主要负责日期的转换与格式化,但在多线程的环境中,使用此类容易造成数据转换及处理的不正确,因为SimpleDateFormat并不是线程安全的,我们看一段代码:

    package chapter7.testsimpledateformat;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class MyThread extends Thread{
    	
    	private SimpleDateFormat sdf;
    	private String dateString;
    	
    	public MyThread(SimpleDateFormat sdf,String dateString) {
    		this.sdf = sdf;
    		this.dateString = dateString;
    	}
    	
    	@Override
    	public void run() {
    		try {
    			super.run();
    			Date dateRef = sdf.parse(dateString);
    			String newDateStr = sdf.format(dateRef).toString();
    			if(!newDateStr.equals(dateString)) {
    				System.out.println("ThreadName="+this.getName()+"报错了 日期字符串:"+dateString+" 转换成的日期为:"+newDateStr);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    }
    
    package chapter7.testsimpledateformat;
    
    import java.text.SimpleDateFormat;
    
    public class Test {
    	
    	public static void main(String[] args) {
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    		String[] dateStr = new String[] {"2000-01-01","2000-01-02","2000-01-03","2000-01-04","2000-01-05","2000-01-06","2000-01-07","2000-01-08","2000-01-09","2000-01-10"};
    		MyThread[] threads = new MyThread[10];
    		for(int i=0;i<10;i++) {
    			threads[i] = new MyThread(sdf, dateStr[i]);
    		}
    		for(int i=0;i<10;i++) {
    			threads[i].start();
    		}
    	}
    
    }
    

     运行结果:

    ThreadName=Thread-5报错了 日期字符串:2000-01-06 转换成的日期为:2000-01-02
    ThreadName=Thread-6报错了 日期字符串:2000-01-07 转换成的日期为:2000-01-01
    ThreadName=Thread-2报错了 日期字符串:2000-01-03 转换成的日期为:2000-01-05
    ThreadName=Thread-3报错了 日期字符串:2000-01-04 转换成的日期为:0010-01-10
    ThreadName=Thread-4报错了 日期字符串:2000-01-05 转换成的日期为:2000-01-10

    解决办法1:

    package chapter7.testsimpledateformat;
    
    import java.util.Date;
    
    public class MyThread extends Thread{
    	
    	private String dateString;
    	
    	public MyThread(String dateString) {
    		this.dateString = dateString;
    	}
    	
    	@Override
    	public void run() {
    		try {
    			super.run();
    			Date dateRef = DateTools.parse(dateString);
    			String newDateStr = DateTools.format(dateRef);
    			if(!newDateStr.equals(dateString)) {
    				System.out.println("ThreadName="+this.getName()+"报错了 日期字符串:"+dateString+" 转换成的日期为:"+newDateStr);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    }
    
    package chapter7.testsimpledateformat;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class DateTools {
    	
    	private static final String DATE_FORMAT = "yyyy-MM-dd";
    	
    	public static Date parse(String dateStr) throws ParseException {
    		return new SimpleDateFormat(DATE_FORMAT).parse(dateStr);
    	}
    	
    	public static String format(Date date){
    		return new SimpleDateFormat(DATE_FORMAT).format(date);
    	}
    
    }
    
    package chapter7.testsimpledateformat;
    
    public class Test {
    	
    	public static void main(String[] args) {
    		try {
    			String[] dateStr = new String[] {"2000-01-01","2000-01-02","2000-01-03","2000-01-04","2000-01-05","2000-01-06","2000-01-07","2000-01-08","2000-01-09","2000-01-10"};
    			MyThread[] threads = new MyThread[10];
    			for(int i=0;i<10;i++) {
    				threads[i] = new MyThread(dateStr[i]);
    			}
    			for(int i=0;i<10;i++) {
    				threads[i].start();
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    
    	}
    
    }
    

     运行结果:没有打印错误,说明问题解决,解决处理错误的原理其实就是创建多个SimpleDateFormat。

    解决方法2:

    package chapter7.testsimpledateformat;
    
    import java.util.Date;
    
    public class MyThread extends Thread{
    	
    	private String dateString;
    	
    	public MyThread(String dateString) {
    		this.dateString = dateString;
    	}
    	
    	@Override
    	public void run() {
    		try {
    			super.run();
    			Date dateRef = DateTools.getSimpleDateFormat().parse(dateString);
    			String newDateStr = DateTools.getSimpleDateFormat().format(dateRef);
    			if(!newDateStr.equals(dateString)) {
    				System.out.println("ThreadName="+this.getName()+"报错了 日期字符串:"+dateString+" 转换成的日期为:"+newDateStr);
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    }
    
    package chapter7.testsimpledateformat;
    
    import java.text.SimpleDateFormat;
    
    public class DateTools {
    	
    	private static final String DATE_FORMAT = "yyyy-MM-dd";
    	private static ThreadLocal<SimpleDateFormat> tlLocal = new ThreadLocal<SimpleDateFormat>();
    	
    	public static SimpleDateFormat getSimpleDateFormat() {
    		SimpleDateFormat sdf = null;
    		sdf = tlLocal.get();
    		if(sdf == null) {
    			sdf = new SimpleDateFormat(DATE_FORMAT);
    			tlLocal.set(sdf);
    		}
    		return sdf;
    	}
    	
    }
    

     运行结果:没有输出错误,说明用ThreadLocal可以解决问题,ThreadLocal类能使线程绑定到指定的对象。

  • 相关阅读:
    IDEA tomcat热部署方法及乱码问题解决
    访问WEB-INF下JSP资源的几种方式(转)
    SpringMVC 静态资源处理
    SpringMVC中的拦截器
    SpringMVC中的异常处理
    SpringMVC实现文件上传
    IDEA 热部署
    响应数据和结果视图
    SpringMVC中的常用注解
    js获取当前根目录的方法
  • 原文地址:https://www.cnblogs.com/hunter-56213/p/11102834.html
Copyright © 2011-2022 走看看