SimpleDateFormat-多线程问题:
SimpleDateFormat类在多线程环境下中处理日期,极易出现日期转换错误的情况
1 import java.text.ParseException; 2 import java.text.SimpleDateFormat; 3 import java.util.Date; 4 5 /** 6 * 线程类 7 */ 8 public class MyThread extends Thread { 9 10 private SimpleDateFormat sdf; 11 private String dateString; 12 13 public MyThread(SimpleDateFormat sdf,String dateString) { 14 this.sdf = sdf; 15 this.dateString = dateString; 16 } 17 18 @Override 19 public void run() { 20 try { 21 Date dateRef = sdf.parse(dateString); 22 String newDateString = sdf.format(dateRef).toString(); 23 if(!newDateString.equals(dateString)) { 24 System.out.println("ThreadName = " + Thread.currentThread().getName() 25 + "报错了 日期字符串:" + dateString + "转换成日期为:" + newDateString); 26 } 27 } catch (ParseException e) { 28 e.printStackTrace(); 29 } 30 } 31 }
1 import java.text.SimpleDateFormat; 2 3 public class Test { 4 5 /** 6 * 测试单例的SimpleDateFormat类在多线程环境下中处理日期,极易出现日期转换错误的情况 7 */ 8 public static void main(String[] args) { 9 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 10 String[] dateStringArray = new String[] { 11 "2000-01-01","2000-01-02","2000-01-03", 12 "2000-01-04","2000-01-05","2000-01-06", 13 "2000-01-07","2000-01-08","2000-01-09", 14 "2000-01-10" 15 }; 16 17 MyThread[] threadArray = new MyThread[10]; 18 for (int i = 0; i < 10; i++) { 19 threadArray[i] = new MyThread(sdf, dateStringArray[i]); 20 } 21 for (int i = 0; i < 10; i++) { 22 threadArray[i].start(); 23 } 24 } 25 }
运行之后会输出很多的错误信息!
解决多线程出现的问题-为每个线程实例一个SimpleDateFormat:
1 import java.text.ParseException; 2 import java.util.Date; 3 4 /** 5 * 线程类 6 */ 7 public class MyThread extends Thread { 8 9 private String dateString; 10 public MyThread(String dateString) { 11 this.dateString = dateString; 12 } 13 14 @Override 15 public void run() { 16 try { 17 Date dateRef = DateTools.parse("yyyy-MM-dd", dateString); 18 String newDateString = DateTools.format("yyyy-MM-dd",dateRef).toString(); 19 if(!newDateString.equals(dateString)) { 20 System.out.println("ThreadName = " + Thread.currentThread().getName() 21 + "报错了 日期字符串:" + dateString + "转换成日期为:" + newDateString); 22 } 23 } catch (ParseException e) { 24 e.printStackTrace(); 25 } 26 } 27 }
1 import java.text.ParseException; 2 import java.text.SimpleDateFormat; 3 import java.util.Date; 4 5 /** 6 * 日期格式化工具类 7 */ 8 public class DateTools { 9 10 public static Date parse(String formatPattern,String dateString) throws ParseException { 11 return new SimpleDateFormat(formatPattern).parse(dateString); 12 } 13 14 public static String format(String formatPattern,Date date) throws ParseException { 15 return new SimpleDateFormat(formatPattern).format(date).toString(); 16 } 17 }
1 public class Test { 2 3 /** 4 * 测试,运行程序后,控制台没有任何输出,也就是转换没有任何异常, 5 * 原理:创建了多个SimpleDateFormat实例 6 */ 7 public static void main(String[] args) { 8 String[] dateStringArray = new String[] { 9 "2000-01-01","2000-01-02","2000-01-03", 10 "2000-01-04","2000-01-05","2000-01-06", 11 "2000-01-07","2000-01-08","2000-01-09", 12 "2000-01-10" 13 }; 14 15 MyThread[] threadArray = new MyThread[10]; 16 for (int i = 0; i < 10; i++) { 17 threadArray[i] = new MyThread(dateStringArray[i]); 18 } 19 for (int i = 0; i < 10; i++) { 20 threadArray[i].start(); 21 } 22 } 23 }
解决多线程出现的问题-使用ThreadLocal:
1 import java.text.ParseException; 2 import java.util.Date; 3 4 /** 5 * 线程类 6 */ 7 public class MyThread extends Thread { 8 9 private String dateString; 10 public MyThread(String dateString) { 11 this.dateString = dateString; 12 } 13 14 @Override 15 public void run() { 16 try { 17 Date dateRef = DateTools.getSimpleDateFormat("yyyy-MM-dd").parse(dateString); 18 String newDateString = DateTools.getSimpleDateFormat("yyyy-MM-dd").format(dateRef).toString(); 19 if(!newDateString.equals(dateString)) { 20 System.out.println("ThreadName = " + Thread.currentThread().getName() 21 + "报错了 日期字符串:" + dateString + "转换成日期为:" + newDateString); 22 } 23 } catch (ParseException e) { 24 e.printStackTrace(); 25 } 26 } 27 }
1 import java.text.SimpleDateFormat; 2 3 /** 4 * 日期格式化工具类,使用ThreadLocal解决SimpleDateFormat非线程安全问题 5 */ 6 public class DateTools { 7 8 private static ThreadLocal<SimpleDateFormat> t1 = new ThreadLocal<>(); 9 10 public static SimpleDateFormat getSimpleDateFormat(String datePattern) { 11 SimpleDateFormat sdf = null; 12 sdf = t1.get(); 13 if(sdf == null) { 14 sdf = new SimpleDateFormat(datePattern); 15 t1.set(sdf); 16 } 17 return sdf; 18 } 19 }
1 public class Test { 2 3 /** 4 * 测试,运行程序后,控制台没有任何输出,也就是转换没有任何异常 5 * 原理:每个线程都会有自己的ThreadLocal存储全局变量,也就是每个线程都有自己的SimpleDateFormat实例 6 */ 7 public static void main(String[] args) { 8 String[] dateStringArray = new String[] { 9 "2000-01-01","2000-01-02","2000-01-03", 10 "2000-01-04","2000-01-05","2000-01-06", 11 "2000-01-07","2000-01-08","2000-01-09", 12 "2000-01-10" 13 }; 14 15 MyThread[] threadArray = new MyThread[10]; 16 for (int i = 0; i < 10; i++) { 17 threadArray[i] = new MyThread(dateStringArray[i]); 18 } 19 for (int i = 0; i < 10; i++) { 20 threadArray[i].start(); 21 } 22 } 23 }