SimpleDateFormat-多线程问题:

  SimpleDateFormat类在多线程环境下中处理日期,极易出现日期转换错误的情况

 import java.text.ParseException;
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 {
Date dateRef = sdf.parse(dateString);
String newDateString = sdf.format(dateRef).toString();
if(!newDateString.equals(dateString)) {
System.out.println("ThreadName = " + Thread.currentThread().getName()
+ "报错了 日期字符串:" + dateString + "转换成日期为:" + newDateString);
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
 import java.text.SimpleDateFormat;

 public class Test {

     /**
* 测试单例的SimpleDateFormat类在多线程环境下中处理日期,极易出现日期转换错误的情况
*/
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String[] dateStringArray = 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[] threadArray = new MyThread[10];
for (int i = 0; i < 10; i++) {
threadArray[i] = new MyThread(sdf, dateStringArray[i]);
}
for (int i = 0; i < 10; i++) {
threadArray[i].start();
}
}
}

运行之后会输出很多的错误信息!

  解决多线程出现的问题-为每个线程实例一个SimpleDateFormat:

 import java.text.ParseException;
import java.util.Date; /**
* 线程类
*/
public class MyThread extends Thread { private String dateString;
public MyThread(String dateString) {
this.dateString = dateString;
} @Override
public void run() {
try {
Date dateRef = DateTools.parse("yyyy-MM-dd", dateString);
String newDateString = DateTools.format("yyyy-MM-dd",dateRef).toString();
if(!newDateString.equals(dateString)) {
System.out.println("ThreadName = " + Thread.currentThread().getName()
+ "报错了 日期字符串:" + dateString + "转换成日期为:" + newDateString);
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
 import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; /**
* 日期格式化工具类
*/
public class DateTools { public static Date parse(String formatPattern,String dateString) throws ParseException {
return new SimpleDateFormat(formatPattern).parse(dateString);
} public static String format(String formatPattern,Date date) throws ParseException {
return new SimpleDateFormat(formatPattern).format(date).toString();
}
}
 public class Test {

     /**
* 测试,运行程序后,控制台没有任何输出,也就是转换没有任何异常,
* 原理:创建了多个SimpleDateFormat实例
*/
public static void main(String[] args) {
String[] dateStringArray = 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[] threadArray = new MyThread[10];
for (int i = 0; i < 10; i++) {
threadArray[i] = new MyThread(dateStringArray[i]);
}
for (int i = 0; i < 10; i++) {
threadArray[i].start();
}
}
}

  解决多线程出现的问题-使用ThreadLocal:

 import java.text.ParseException;
import java.util.Date; /**
* 线程类
*/
public class MyThread extends Thread { private String dateString;
public MyThread(String dateString) {
this.dateString = dateString;
} @Override
public void run() {
try {
Date dateRef = DateTools.getSimpleDateFormat("yyyy-MM-dd").parse(dateString);
String newDateString = DateTools.getSimpleDateFormat("yyyy-MM-dd").format(dateRef).toString();
if(!newDateString.equals(dateString)) {
System.out.println("ThreadName = " + Thread.currentThread().getName()
+ "报错了 日期字符串:" + dateString + "转换成日期为:" + newDateString);
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
 import java.text.SimpleDateFormat;

 /**
* 日期格式化工具类,使用ThreadLocal解决SimpleDateFormat非线程安全问题
*/
public class DateTools { private static ThreadLocal<SimpleDateFormat> t1 = new ThreadLocal<>(); public static SimpleDateFormat getSimpleDateFormat(String datePattern) {
SimpleDateFormat sdf = null;
sdf = t1.get();
if(sdf == null) {
sdf = new SimpleDateFormat(datePattern);
t1.set(sdf);
}
return sdf;
}
}
 public class Test {

     /**
* 测试,运行程序后,控制台没有任何输出,也就是转换没有任何异常
* 原理:每个线程都会有自己的ThreadLocal存储全局变量,也就是每个线程都有自己的SimpleDateFormat实例
*/
public static void main(String[] args) {
String[] dateStringArray = 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[] threadArray = new MyThread[10];
for (int i = 0; i < 10; i++) {
threadArray[i] = new MyThread(dateStringArray[i]);
}
for (int i = 0; i < 10; i++) {
threadArray[i].start();
}
}
}

SimpleDateFormat-多线程问题的更多相关文章

  1. ThreadLocal解决SimpleDateFormat多线程安全问题中遇到的困惑

    测试代码: public class Main { public static void main(String[] args) { for (int k = 0; k < 10; k++) { ...

  2. java 多线程:线程安全问题,示例DateFormat多线程执行冲突解决方案ThreadLocal、方法内变量

    SimpleDateFormat多线程中执行报错 java.lang.NumberFormatException: For input string: ""   import ja ...

  3. JEECG 3.7.1 版本发布,企业级JAVA快速开发平台

    JEECG 3.7.1 版本发布,企业级JAVA快速开发平台 ---------------------------------------- Version:  Jeecg_3.7.1项 目:   ...

  4. ThreadLocal知识点

    ThreadLocal是什么 ThreadLocal 表面上看他是和多线程,线程同步有关的一个工具类,但其实他与线程同步机制无关.线程同步机制是多个线程共享同一个变量,而ThreadLocal是为每个 ...

  5. JAVA中计算两个日期时间的差值竟然也有这么多门道

    上半年春招的时候,作为面试官,对于面试表现的不错的同学会要求其写一小段代码看看.题目很简单: 给定一个日期,然后计算下距离今天相差的天数. 本以为这么个问题就是用来活跃面试氛围的,但是结果却让人大跌眼 ...

  6. SimpleDateFormat做成员或者静态成员多线程安全隐患

    转自:http://blog.csdn.net/jeamking/article/details/7183958 有时我们在同一个类中都是使用同一种日期格式,又或者为了减少new SimpleDate ...

  7. 【多线程补充】SimpleDateFormat非线程安全与线程中、线程组中异常的处理

    1.SimpleDateFormat非线程安全的问题 类SimpleDateFormat主要负责日期的转换与格式化,但在多线程环境中,使用此类容易造成数据转换及处理的不正确,因为SimpleDateF ...

  8. Java多线程:SimpleDateFormat

    一.SimpleDateFormat的线程安全问题 为什么SimpleDateFormat是线程不安全的? 下面通过一个案例代码来说明 public class DateUtilTest { publ ...

  9. Java多线程(三)SimpleDateFormat

    多线程报错:java.lang.NumberFormatException: multiple points SimpleDateFormat是非线程安全的,在多线程情况下会有问题,在每个线程下得各自 ...

  10. 多线程避免使用SimpleDateFormat及替代方案

    先来看一个多线程下使用例子,看到运行结果会出现异常: import java.text.DateFormat; import java.text.SimpleDateFormat; import ja ...

随机推荐

  1. IIFE 立即执行的函数表达式

    介绍IIFE IIFE的性能 使用IIFE的好处 IIFE最佳实践 jQuery优化 在Bootstrap源码(具体请看<Bootstrap源码解析>)和其他jQuery插件经常看到如下的 ...

  2. LeetCode OJ:Binary Tree Paths(二叉树路径)

    Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree: 1 ...

  3. PHP用mysql_insert_id()函数获得刚插入数据或当前发布文章的ID

    向mysql 插入数据时,很多时候我们想知道刚刚插入数据的id,这对我们很有用.下面这篇文章就详细给大家介绍了利用mysql_insert_id()函数获得刚插入数据或当前发布文章的ID,有需要的朋友 ...

  4. SFTP服务器使用指南(1)——安装搭建freeSSHd

    为什么选择freeSSHd 此软件免费 功能非常丰富且强大,同时支持软件用户.本地系统用户和域用户验证 对各用户选择性开放SFTP,Telnet, Tunneling服务 功能和服务完全不受限制的使用 ...

  5. 如何显示PHP运行错误

    在运行文件的最前面加两行代码: error_reporting(E_ALL); ini_set('display_errors', '1'); 这样调试起来就方便多了

  6. UVA - 10934 Dropping water balloons (dp,逆向思维)

    题目链接 题目大意:给你n个规格一样的气球和一栋大楼的高度,求最少试验几次能测出气球最高在哪一层掉下来不破. 如果这道题想用(dp[i][j]=用i个气球测出j高度的楼需要几次)来作为状态的话,那你就 ...

  7. GO语言heap剖析及利用heap实现优先级队列

    GO语言heap剖析 本节内容 heap使用 heap提供的方法 heap源码剖析 利用heap实现优先级队列 1. heap使用 在go语言的标准库container中,实现了三中数据类型:heap ...

  8. linux下查找命令两则

    由于本人不会阅读man手册,因此需要几下两个常用的查找命令: (1)在某个目录及其子目录查找某个文件并打印完整路径: find ./ -name "assertions.h" -e ...

  9. [转]angular的路由机制

    在谈路由机制前有必要先提一下现在比较流行的单页面应用,就是所谓的single page APP.为了实现无刷新的视图切换,我们通常会用ajax请求从后台取数据,然后套上HTML模板渲染在页面上,然而a ...

  10. Python collections系列之计数器

    计数器(counter) Counter是对字典(无序)类型的补充,用于追踪值的出现次数. 使用counter需要导入 collections 类 ps:具备字典的所有功能 + 自己的功能 1.创建一 ...