服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

使用simpledateformat必须注意的问题


  在使用simpledateformat的经常会有一些错误的用法,例如如下方式:
使用simpledateformat必须注意的问题(图一)使用simpledateformat必须注意的问题(图二)public class testdateformat使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)     private simpledateformat sdf = new simpledateformat("yyyy-mm-dd");
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)     public void method1()使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)         sdf.format(new date());
使用simpledateformat必须注意的问题(图七)     }
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)     public void method2()使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)         sdf.format(new date());
使用simpledateformat必须注意的问题(图七)     }
使用simpledateformat必须注意的问题(图四) )
为了渐少new 的次数而把simpledateformat做成成员或者静态成员,但这样的做法是隐含着错误的,是不
 安全的。如下给出证明:
使用simpledateformat必须注意的问题(图八) import java.text.simpledateformat;
使用simpledateformat必须注意的问题(图八)import java.util.date;
使用simpledateformat必须注意的问题(图八)import java.util.hashmap;
使用simpledateformat必须注意的问题(图八)import java.util.map;
使用simpledateformat必须注意的问题(图八)
使用simpledateformat必须注意的问题(图八)
使用simpledateformat必须注意的问题(图一)使用simpledateformat必须注意的问题(图二)public class testdateformat使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)    private simpledateformat sdf ;
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)    public static void main(string[] args) 使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)        simpledateformat sdf= new simpledateformat("yyyy-mm-dd");
使用simpledateformat必须注意的问题(图四)        date date1 = new date();
使用simpledateformat必须注意的问题(图四)        date date2 = new date(date1.gettime()+1000*60*60*24);
使用simpledateformat必须注意的问题(图四)        system.out.println(date1);
使用simpledateformat必须注意的问题(图四)        system.out.println(date2);
使用simpledateformat必须注意的问题(图四)        thread thread1 = new thread(new thread1(sdf,date1));
使用simpledateformat必须注意的问题(图四)        thread1.start();
使用simpledateformat必须注意的问题(图四)        thread thread2 = new thread(new thread2(sdf,date2));
使用simpledateformat必须注意的问题(图四)        thread2.start();
使用simpledateformat必须注意的问题(图七)    }
使用simpledateformat必须注意的问题(图四)    
使用simpledateformat必须注意的问题(图九)}
使用simpledateformat必须注意的问题(图一)使用simpledateformat必须注意的问题(图二)class thread1 implements runnable使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)    private simpledateformat sdf;
使用simpledateformat必须注意的问题(图四)    private date date;
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)    public thread1(simpledateformat sdf,date date)使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)        this.sdf = sdf;
使用simpledateformat必须注意的问题(图四)        this.date = date;
使用simpledateformat必须注意的问题(图七)    }
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)    public void run() 使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)        for(;;)使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)            string strdate = sdf.format(date);
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)            if("2007-02-27".equals(strdate))使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)                system.err.println("error: date1="+strdate);
使用simpledateformat必须注意的问题(图四)                system.exit(0);
使用simpledateformat必须注意的问题(图七)            }
使用simpledateformat必须注意的问题(图七)        }
使用simpledateformat必须注意的问题(图七)    }
使用simpledateformat必须注意的问题(图九)}
使用simpledateformat必须注意的问题(图一)使用simpledateformat必须注意的问题(图二)class thread2 implements runnable使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)    private simpledateformat sdf;
使用simpledateformat必须注意的问题(图四)    private date date;
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)    public thread2(simpledateformat sdf,date date)使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)        this.sdf = sdf;
使用simpledateformat必须注意的问题(图四)        this.date = date;
使用simpledateformat必须注意的问题(图七)    }
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)    public void run() 使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)        for(;;)使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)            string strdate = sdf.format(date);
使用simpledateformat必须注意的问题(图五)使用simpledateformat必须注意的问题(图六)            if("2007-02-26".equals(strdate))使用simpledateformat必须注意的问题(图三){
使用simpledateformat必须注意的问题(图四)                system.err.println("error: date1="+strdate);
使用simpledateformat必须注意的问题(图四)                system.exit(0);
使用simpledateformat必须注意的问题(图七)            }
使用simpledateformat必须注意的问题(图七)        }
使用simpledateformat必须注意的问题(图七)    }
使用simpledateformat必须注意的问题(图九)}

很快,基本几十次就会出现错误。错误原因:
 因为simpledateformat处理复杂,jdk的实现中使用了成员变量来传递参数,这个就造成在多线程的时候
 会出现错误。上边的程序证明了这个问题。
 
 再看看simpledateformat的jdk 的source,有这么一段注释,说明它不是线程安全的。
 date formats are not synchronized.
 * it is recommended to create separate format instances for each thread.
 * if multiple threads access a format concurrently, it must be synchronized
 
 继续看看sun自己的网站上。在sun的bug database中
 bug id:  4228335  讲的就是这个问题。
 simpledateformat is not threadsafe (one more try)
 其中有这么几段话值得关注:
 1,
 aside from the obvious, there are two reasons why this fix should be made:
- the documentation for dateformat states that a dateformat object should be used
multiple times, implying that construction is expensive.  furthermore,
 no mention is made of simpledateformat's lack of thread-safety. 
 since for most applications the date formats remain constant,
 it is very easy to conclude that dateformats should be application globals.
 but simpledateformat produces incorrect results when used in this way.
- bug 4101500, a similar problem with numberformat, was fixed.

建议修改这个问题,而且numberformat已经修改,解决了这个问题。简单测试了一下numberformat确是不出错

2,
use of a cloned calendar object in format(), as suggested in jdc comments,
slows down the execution 30-50%. and it potentially affects footprint because
of cloned objects. another approach would be to have a calendar instance per
thread. however, this approach will cause problems at the api semantic level due
to the get/setcalendar methods.
这一段解释了为什么没修改这个问题,一个是保持api不变,另一个是因为clone比new慢,会损失效率
关于clone与new的快慢,看这里http://www.blogjava.net/dreamstone/archive/2007/02/26/100761.html。

其它的还有好多,感兴趣的自己看看吧。

结论:每次使用它的时候现new,或者用一个同步函数把new好的包装起来使用吧。

扫描关注微信公众号