SimpleDateFormat非线程不安全

来源:互联网 发布:詹姆斯生涯场均数据 编辑:程序博客网 时间:2024/06/06 01:17

1 单线程环境

类SimpleDateFormate常用于时间格式转换,在单线程环境下运行结果正常,如下所示

public class MyThread extends Thread {   private SimpleDateFormatsdf;   private StringdateString;    publicMyThread(SimpleDateFormatsdf, String dateString) {      this.sdf =sdf;      this.dateString =dateString;   }    Public void run() {      try {        Date date = sdf.parse(dateString);        String newDateString = sdf.format(date).toString();        if (!newDateString.equals(dateString)) {           System.out.println("日期字符串: " + dateString + "转换成日期为:" +newDateString);        }      } catch(ParseExceptione) {        e.printStackTrace();      }   }}
public class SingleThreadTest{   public static void main(String[]args) {      SimpleDateFormat sdf = newSimpleDateFormat("yyyy-MM-dd");      String[] dateStringArray = new String[]{"2017-01-01","2017-01-02", "2017-01-03","2017-01-04", "2000-01-05",           "2017-01-06", "2017-01-07", "2017-01-08", "2017-01-09", "2017-01-10"};      MyThread[] threadArray = newMyThread[10];      for(inti = 0; i < 10;i++){        threadArray[i] = new MyThread(sdf,dateStringArray[i]);      }      for(inti = 0; i < 10;i++){       threadArray[i].run(); //单线程情况下      }   }}

运行结果:


2 并发环境

在并发环境下,使用类SimpleDateFormate进行日期格式转换会出现数据处理不正确,根本原因是存在共享变量calendar

public class MutiThreadTest{   public static void main(String[]args) {      SimpleDateFormat sdf = newSimpleDateFormat("yyyy-MM-dd");      String[] dateStringArray = new String[]{"2017-01-01","2017-01-02", "2017-01-03","2017-01-04", "2000-01-05",           "2017-01-06", "2017-01-07", "2017-01-08", "2017-01-09", "2017-01-10"};      MyThread[] threadArray = newMyThread[10];      for(inti = 0; i < 10;i++){        threadArray[i] = new MyThread(sdf,dateStringArray[i]);      }      for(inti = 0; i < 10;i++){        threadArray[i].start(); //多线程条件下      }   }}


运行结果:

 


3  解决方法

3.1使用 LocalDate类

 JDK8时间新特性类LocalDate是线程安全,而且使用方法更简单

public class Test {   public static void main(String[]args) {      String[] dateStringArray = new String[]{"2017-01-01","2017-01-02", "2017-01-03","2017-01-04", "2000-01-05",           "2017-01-06", "2017-01-07", "2017-01-08", "2017-01-09", "2017-01-10"};      MyThread[] threadArray = newMyThread[10];      for(inti = 0; i < 10;i++){        threadArray[i] = new MyThread(dateStringArray[i]);      }      for(inti = 0; i < 10;i++){        threadArray[i].start();  //多线程条件下             }   }}
public class MyThread extends Thread {   private StringdateString;   public MyThread(StringdateString) {      super();      this.dateString =dateString;   }    public void run() {      LocalDate date = LocalDate.parse(dateString);// JDK8新特性      if (!date.toString().equals(dateString)) {        System.out.println("日期字符串: " +dateString + "转换成日期为:" +date);      }   }} 

3.2 使用ThreadLocal类

类ThreadLocal解决的是变量在不同线程间的隔离性,也就是不同线程拥有自己的隔离值,不同线程中的值可以放入ThreadLocal类中进行保存。

public class DateTools{   privatestaticThreadLocal<SimpleDateFormat> t1 = newThreadLocal<SimpleDateFormat>();   publicstaticSimpleDateFormat getSimpleDateFormate(StringdatePattern){      SimpleDateFormat sdf = null;      sdf = t1.get();      if(sdf ==null){        sdf = newSimpleDateFormat(datePattern);        t1.set(sdf);      }      returnsdf;   }}
public class MyThread extends Thread {   private StringdateString;     public MyThread(StringdateString) {      super();      this.dateString =dateString;   }    publicvoid run(){      try {           Date dateRef =DateTools.getSimpleDateFormate("yyyy-MM-dd").parse(dateString);        String newDateString =  DateTools.getSimpleDateFormate("yyyy-MM-dd").format(dateRef).toString();        if (!newDateString.equals(dateString)) {           System.out.println("日期字符串: " + dateString + "转换成日期为:" +newDateString);        }      } catch(ParseExceptione) {        e.printStackTrace();      }       }}
public class Test {   publicstatic voidmain(String[]args) {      String[] dateStringArray = new String[]{"2017-01-01","2017-01-02", "2017-01-03","2017-01-04", "2000-01-05",           "2017-01-06", "2017-01-07", "2017-01-08", "2017-01-09", "2017-01-10"};      MyThread[] threadArray = newMyThread[10];      for(inti = 0; i < 10;i++){        threadArray[i] = newMyThread(dateStringArray[i]);      }      for(inti = 0; i < 10;i++){        threadArray[i].start();  //多线程条件下             }   }}

4 参考文献

[1]  高洪岩, Java多线程编程核心技术. 2015.

[2]  Goetz, B.等, Java 并发编程实战. 2012.

[3]  https://docs.oracle.com/javase/8/docs/api/index.html


阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 威海中汇大酒店 中汇广场地址 汇丰小区 汇丰凯苑 汇丰沁苑 汇丰苑大酒店 青岛汇丰苑大酒店 汇捷装修 启功书法字汇下载 侨鑫汇悦台什么人住的 汇景新城都是有钱人吗 广州汇侨新城 汇元网 汇金钱包 汇博企业版 博汇教育公司好吗 重庆汇博人才 汇博人才网下载 合川汇博人才网 铜梁汇博人才网 汇博人才网璧山招聘 重庆英才网 福州597人才网 漳州597人才网 重庆找工作求职 重庆人才市场地址 重庆招工 重庆工作招聘信息 重庆市人才市场招聘 重庆近期招聘会 重庆市人才市场 重庆市人才招聘会 重庆招工信息 厦门海峡人才网 重庆智联人才网 重庆联英人才网 汇博苑 贵阳群升大智汇 中建群贤汇 吉水汇通 汇吉网