Java之——SimpleDateFormat 线程不安全问题及解决方法
2016-12-18 15:54
886 查看
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/53727922
今天,给大家带来一篇Java SimpleDateFormat在多线程环境下不安全的文章,Java SimpleDateFormat 是线程不安全的,当在多线程环境下使用一个DateFormat的时候是有问题的,如下面的例子
一、问题
异常1:
今天,给大家带来一篇Java SimpleDateFormat在多线程环境下不安全的文章,Java SimpleDateFormat 是线程不安全的,当在多线程环境下使用一个DateFormat的时候是有问题的,如下面的例子
package com.lya.date; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * SimpleDateFormat在多线程下会变得不安全 * @author liuyazhuang * */ public class DateFormatTest { private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static void main(String[] args) throws Exception { Callable<Date> task = new Callable<Date>() { public Date call() throws Exception { return format.parse("2016-12-18 15:00:00"); } }; // 创建5个线程的线程池 ExecutorService exec = Executors.newFixedThreadPool(5); List<Future<Date>> results = new ArrayList<Future<Date>>(); for (int i = 0; i < 10; i++) { results.add(exec.submit(task)); } exec.shutdown(); // 输出结果 for (Future<Date> result : results) { System.out.println(result.get()); } } }
一、问题
异常1:Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NumberFormatException: multiple points at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:192) at com.lya.date.DateFormatThreadSafe.main(DateFormatThreadSafe.java:35) Caused by: java.lang.NumberFormatException: multiple points at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1890) 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:2056) 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.lya.date.DateFormatThreadSafe$1.call(DateFormatThreadSafe.java:23) at com.lya.date.DateFormatThreadSafe$1.call(DateFormatThreadSafe.java:1) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)异常2
Sun Dec 18 15:00:00 CST 2016 Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NumberFormatException: For input string: "E.2122" at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:192) at com.lya.date.DateFormatThreadSafe.main(DateFormatThreadSafe.java:35) Caused by: java.lang.NumberFormatException: For input string: "E.2122" at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043) 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:2056) 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.lya.date.DateFormatThreadSafe$1.call(DateFormatThreadSafe.java:23) at com.lya.date.DateFormatThreadSafe$1.call(DateFormatThreadSafe.java:1) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)异常3
Sun Dec 18 15:00:00 CST 2016 Sun Jan 14 00:00:00 CST 4317 Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NumberFormatException: For input string: "" at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:192) at com.lya.date.DateFormatThreadSafe.main(DateFormatThreadSafe.java:35) Caused by: java.lang.NumberFormatException: For input string: "" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Long.parseLong(Long.java:601) at java.lang.Long.parseLong(Long.java:631) at java.text.DigitList.getLong(DigitList.java:195) at java.text.DecimalFormat.parse(DecimalFormat.java:2051) 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.lya.date.DateFormatThreadSafe$1.call(DateFormatThreadSafe.java:23) at com.lya.date.DateFormatThreadSafe$1.call(DateFormatThreadSafe.java:1) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
二、解决方案
我们可以将把DateFormat 放到ThreadLocal中解决线程安全问题,如下所示package com.lya.date; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * 解决SimpleDateFormat线程安全问题 * @author liuyazhuang * */ public class DateFormatThreadSafe { private static final ThreadLocal<DateFormat> DF = new ThreadLocal<DateFormat>() { @Override protected DateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } }; public static Date convert(String source) throws ParseException { Date d = DF.get().parse(source); return d; } }测试代码如下:
package com.lya.date; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * 测试线程安全的DateFormat * @author liuyazhuang * */ public class DateTest { public static void main(String[] args) throws Exception { Callable<Date> task = new Callable<Date>() { public Date call() throws Exception { return DateFormatThreadSafe.convert("2016-12-18 15:00:00"); } }; // 创建5个线程的线程池 ExecutorService exec = Executors.newFixedThreadPool(5); List<Future<Date>> results = new ArrayList<Future<Date>>(); for (int i = 0; i < 10; i++) { results.add(exec.submit(task)); } exec.shutdown(); // 输出结果 for (Future<Date> result : results) { System.out.println(result.get()); } } }输出结果如下:
Sun Dec 18 15:00:00 CST 2016 Sun Dec 18 15:00:00 CST 2016 Sun Dec 18 15:00:00 CST 2016 Sun Dec 18 15:00:00 CST 2016 Sun Dec 18 15:00:00 CST 2016 Sun Dec 18 15:00:00 CST 2016 Sun Dec 18 15:00:00 CST 2016 Sun Dec 18 15:00:00 CST 2016 Sun Dec 18 15:00:00 CST 2016 Sun Dec 18 15:00:00 CST 2016至此,Java中的SimpleDateFormat就是线程安全的了。
相关文章推荐
- 解决SimpleDateFormat的线程不安全问题的方法:ThreadLocal
- Java SimpleDateFormat 线程不安全问题及解决方法
- 程序中和有js函数的网页交互,线程中调用 get_Script 就会错误的解决方法,由于COM的线程安全问题
- SimpleDateFormat线程不安全示例及其解决方法
- java解决线程不安全问题的方法
- SimpleDateFormat 的线程安全问题与解决方式
- 13.8 线程的安全问题和解决方法
- 一个简单的Java对象池实现——可用来解决SimpleDateFormat的线程安全问题
- SimpleDateFormat线程不安全及解决的方法
- Java线程安全问题及线程安全解决方法
- 线程安全问题出现的原因和解决方法
- 四种方法解决存储过程中的数据安全问题
- swftools转换文件时线程堵塞问题的解决方法
- flex关于跨域访问会引起安全沙箱问题,下面是在网上找到的解决安全沙箱问题的方法
- 浅谈互联网安全的问题以及解决方法
- 做ssl通道时遇到“请求被中止: 未能创建 SSL/TLS 安全通道”问题的解决方法
- MyEclipse6.5_org.tigris.subversion.javahl.ClientException: Unsupported working copy format问题解决方法
- swftools转换文件时线程堵塞问题的解决方法
- ACE的ACE_Logging_Strategy类中的一个多线程安全问题的发现及解决过程
- OpenID与传统Email用户身份认证模式整合时的安全问题和解决方法