小编带你了解SimpleDateFormat-多线程问题

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();
      }
      }
      }

原文地址:http://blog.51cto.com/13954634/2170816

时间: 2024-11-05 21:39:21

小编带你了解SimpleDateFormat-多线程问题的相关文章

小编带您Volatile的详解

volatile关键字修饰的共享变量主要有两个特点:1.保证了不同线程访问的内存可见性 2.禁止重排序在说内存可见性和有序性之前,我们有必要看一下Java的内存模型(注意和JVM内存模型的区分)为什么要有java内存模型?首先我们知道内存访问和CPU指令在执行速度上相差非常大,完全不是一个数量级,为了使得java在各个平台上运行的差距减少,哪些搞处理器的大佬就在CPU上加了各种高速缓存,来减少内存操作和CPU指令的执行速度差距.而Java在java层面又进行了一波抽象,java内存模型将内存分为

小编带您进入SpringBoot (1) idea下的环境搭建及demo

1.Spring Boot简介wiki上的介绍: Spring Boot是Spring的常规配置解决方案,用于创建可以"运行"的独立的,生产级的基于Spring的应用程序.[22]它预先配置了Spring对Spring平台和第三方库的最佳配置和使用的"见解视图",因此您可以尽量少开始.大多数Spring Boot应用程序只需要很少的Spring配置.特征: 创建独立的Spring应用程序直接嵌入Tomcat或Jetty(无需部署WAR文件)提供自以为是的"

小编带你了解Netty 系列七(那些开箱即用的 ChannelHandler).

一.前言Netty 为许多通用协议提供了编×××和处理器,几乎可以开箱即用, 这减少了你在那些相当繁琐的事务上本来会花费的时间与精力.另外,这篇文章中,就不涉及 Netty 对 WebSocket协议 的支持了,因为涉及的篇幅有点大,会在下一篇文章做一个具体的介绍. 回到顶部二.SSL 协议SSL 协议是安全协议,层叠在其他协议之上.为了支持 SSL/TLS, Java 提供了 javax.net.ssl 包,它的 SSLContext 和 SSLEngine 类使得实现解密和加密相当简单直接.

没有基础小编带你,用python画机器猫(有代码)

小编带你玩python 没有基础小编带你,用python画机器猫.只需要python3和小编的代码即可.python3小编送,代码文章有,现在就差个你了. 运行不了的找小编,小编包教会你. 重要的事情说三遍: python3小编送,代码文章有. python3小编送,代码文章有. python3小编送,代码文章有. 运行不了的找小编,加Q君羊 八八三四四四一零六. 君羊里的小伙伴和管理员的会这个运行这个源代码.需要学习视频的直接找管理员要,就说是小编让的,烦死她.欢迎小伙伴的加入. 原文地址:h

小编带你简单了解一下加密技术原理:AES加密标准

随着因特网的发展,信息传输及存储的安全问题成为影响因特网应用发展的重要因素.信息安全技术也就成为了人们研究因特网应用的新热点. 信息安全的研究包括密码理论与技术.安全协议与技术.安全体系结构理论.信息对抗理论与技术.网络安全与安全产品等领域,其中密码算法的理论与实现研究是信息安全研究的基础. AES加密标准1977年1月公布的数据加密标准DES(Data Encrption Standard)经过20年的实践应用后,现在已被认为是不可靠的.1997年1月美国国家标准和技术研究所(NIST)发布了

小编带您学习springboot

一般而言,写个Javaweb应用搭建环境都可能要几十分钟,下载个tomcat服务器,再加上各种xml配置等等,很烦躁,而且每个web应用的配置还差不多,都是什么web.xml,application.xml等等(注解版就是各种配置类@Configuration),既然每个web应用很多配置都一样,那为什么还要每次都动手写或者copy一份呢?假如有什么框架能够帮我们把常用的东西都配置好,有默认值,然后我们只需要关注一些逻辑的编写,那不就大大简化了编程效率吗? 所以就有了springboot,这里s

小编带你进入强如 Disruptor 也发生内存溢出?

前言OutOfMemoryError 问题相信很多朋友都遇到过,相对于常见的业务异常(数组越界.空指针等)来说这类问题是很难定位和解决的. 本文以最近碰到的一次线上内存溢出的定位.解决问题的方式展开:希望能对碰到类似问题的同学带来思路和帮助. 主要从表现-->排查-->定位-->解决 四个步骤来分析和解决问题. 表象最近我们生产上的一个应用不断的爆出内存溢出,并且随着业务量的增长出现的频次越来越高. 该程序的业务逻辑非常简单,就是从 Kafka 中将数据消费下来然后批量的做持久化操作.

小编带你了解Spring Cloud 微服务

Spring Cloud 简介 Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消息总线.负载均衡.断路器.数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署.Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟.经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂.

小编带着小白看springboot源码7

上一节在springboot中配置了servlet三大组件以及嵌入式servlet容器,并且还简单的说了如何切换不同的容器. 这一节就来说说如何改变servlet容器的配置参数,一般有两种常见的方式,第一种:配置文件(properties和yml):第二种:往容器里添加组件的方式 注意注意:我这里说的容器和嵌入式容器不一样的,容器指的是ioc容器,嵌入式servlet容器值得是servlet容器,不要混淆了 1.通过配置文件的方式配置 yml为例,下图所示,这是配置容器启动的端口而且我们可以点开