SimpleDateFormat類非執行緒安全
阿新 • • 發佈:2018-12-27
SimpleDateFormat在多執行緒中會出現執行緒安全問題。
class DateThread extends Thread { private SimpleDateFormat sdf; private String dateString; public DateThread(SimpleDateFormat sdf, String dateString) { this.sdf = sdf; this.dateString = dateString; } @Override public void run() { try { Date date = sdf.parse(dateString); String newDateString = sdf.format(date).toString(); if (!newDateString.equals(dateString)) { System.out.println("ThreadName = " + this.getName() + "報錯了 日期字串:" + dateString + " 轉換成的日期為" + newDateString); } } catch (ParseException e) { e.printStackTrace(); } } } public class Run3_formatError { public static void main(String[] args) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String[] dateStringArray = new String[] { "2018-12-01", "2018-12-02", "2018-12-03", "2018-12-04", "2018-12-05", "2018-12-06", "2018-12-07", "2018-12-08", "2018-12-09", "2018-12-10" }; DateThread[] threads = new DateThread[10]; for (int i = 0; i < 10; i++) { threads[i] = new DateThread(sdf, dateStringArray[i]); } for (int i = 0; i < 10; i++) { threads[i].start(); } } }
報錯:
java.lang.NumberFormatException: For input string: "1212.E12122E2" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Long.parseLong(Long.java:589) at java.lang.Long.parseLong(Long.java:631) at java.text.DigitList.getLong(DigitList.java:195) at java.text.DecimalFormat.parse(DecimalFormat.java:2084) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514) at java.text.DateFormat.parse(DateFormat.java:364) at com.brianway.learning.java.multithread.supplement.example3.DateThread.run(Run3_formatError.java:28) java.lang.NumberFormatException: empty String at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842) at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.lang.Double.parseDouble(Double.java:538) at java.text.DigitList.getDouble(DigitList.java:169) at java.text.DecimalFormat.parse(DecimalFormat.java:2089) at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869) at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514) at java.text.DateFormat.parse(DateFormat.java:364) at com.brianway.learning.java.multithread.supplement.example3.DateThread.run(Run3_formatError.java:28) ThreadName = Thread-1報錯了 日期字串:2018-12-02 轉換成的日期為2222-12-01 ThreadName = Thread-0報錯了 日期字串:2018-12-01 轉換成的日期為2222-12-01
解決:
class DateThread extends Thread { private SimpleDateFormat sdf; private String dateString; //通過本地執行緒池 解決執行緒安全問題 private static ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>(); public DateThread(SimpleDateFormat sdf, String dateString) { this.sdf = sdf; this.dateString = dateString; } public static SimpleDateFormat getSimpleDateFormat(String datePattern) { SimpleDateFormat sdf = null; sdf = tl.get(); if (sdf == null) { sdf = new SimpleDateFormat(datePattern); tl.set(sdf); } return sdf; } @Override public void run() { try { Date date = getSimpleDateFormat("yyyy-MM-dd").parse(dateString); String newDateString = DateTools2.getSimpleDateFormat("yyyy-MM-dd").format(date).toString(); System.out.println(newDateString); if (!newDateString.equals(dateString)) { System.out.println("ThreadName = " + this.getName() + "報錯了 日期字串:" + dateString + " 轉換成的日期為" + newDateString); } } catch (ParseException e) { e.printStackTrace(); } } } public class Run3_formatError { public static void main(String[] args) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String[] dateStringArray = new String[] { "2018-12-01", "2018-12-02", "2018-12-03", "2018-12-04", "2018-12-05", "2018-12-06", "2018-12-07", "2018-12-08", "2018-12-09", "2018-12-10" }; DateThread[] threads = new DateThread[10]; for (int i = 0; i < 10; i++) { threads[i] = new DateThread(sdf, dateStringArray[i]); } for (int i = 0; i < 10; i++) { threads[i].start(); } } }