`
lichaozhangobj
  • 浏览: 98808 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

转:simpledateformat 线程不安全

    博客分类:
  • java
阅读更多

如果一个资源或对象可能被多个线程同时访问,它就是一个共享资源;例如类的成员变量,包括类变量和实例变量,再比如对一个文件进行写操作等。一般情况下,对共享资源的访问需要考虑线程安全的问题。

  如果一个对象的完整生命周期只在一个线程内,则不需要考虑线程安全,例如一个局部变量。下面为一个示例代码:

public class C1 { 

public static java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd"); 

//其他代码 

} 

 

  假如在一个JSP中这样的去调用:

<a.jsp>: 

<% 

Java.util.Date date = C1.sdf.parse(“2003-4-15”); 

%> 

 

  则这样的代码不是线程安全的。因为java.text.SimpleDateFormat不是线程安全的,a.jsp中的代码将会有若干个线程同时执行,而都访问的是同一个线程不安全的对象,这样就不是一个线程安全的代码。正确的写法应该如下:

<a.jsp>: 

<% 

java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd"); 

Java.util.Date date = sdf.parse(“2003-4-15”); 

%> 

 

2、 原因分析:

  此时,sdf对象从创建到销毁都位于一个方法中,相当于一个局部变量,不是一个共享资源,因此则没有线程不安全的问题。

3、 解决方法或过程:

1) 如果对象是immutable,则是线程安全的,例如:String,可以放心使用。
2) 如果对象是线程安全的,则放心使用
3) 有条件线程安全,对于Vector和Hashtable一般情况下是线程安全的,但是对于某些特殊情况,需要通过额外的synchronized保证线程安全。
4) 使用synchronized关键字;

  对于上例中可以改写jsp代码,在sdf上进行同步,而不需要每次创建一个新的对象来保证线程安全,代码如下:

<% 

synchronized(C1.sdf){ 

Java.util.Date date = C1.sdf.parse(“2003-4-15”); 

} 

%> 

 

  这种写法是在一个对象级别上进行同步,也就是说任何时候,对于这个对象,最多只能有一个线程在执行同步方法。

  另外一种写法是在Class级别上进行同步,写法如下:

public class C1 { 

public static java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd"); 



public void method(){ 

synchronized(C1.class){ 

//synchronized code 

} 

} 

} 

 

  这种写法表示无论C1有多少个实例,在任何一个时间点,最多只能有一个线程和一个实例进入同步块中。这种同步会比较大的影响性能。

  5) 有些对象不能在多线程间共享,则只能在方法内部使用,或者只在一个线程内部使用。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics