`
kakaluyi
  • 浏览: 444999 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

转:ThreadLocal示例

阅读更多

 本文借花献佛,引用Tim Cull的博文“SimpleDateFormat: Performance Pig”介绍下ThreadLocal的简单使用,同时也对SimpleDateFormat的使用有个深入的了解。

Tim Cull 写道
Just yesterday I came across this problem “in the wild” for the third time in my career so far: an application with performance problems creating tons of java.text.SimpleDateFormat instances. So, I have to get this out there: creating a new instance of SimpleDateFormat is incredibly expensive and should be minimized. In the case that prompted this post, I was using JProfiler to profile this code that parses a CSV file and discovered that 50% of the time it took to suck in the file and make 55,000 objects out of it was spent solely in the constructor of SimpleDateFormat. It created and then threw away a new one every time it had to parse a date. Whew!

“Great,” you think, “I’ll just create one, static instance, slap it in a field in a DateUtils helper class and life will be good.”

Well, more precisely, life will be good about 97% of the time. A few days after you roll that code into production you’ll discover the second cool fact that’s good to know: SimpleDateFormat is not thread safe. Your code will work just fine most of the time and all of your regression tests will probably pass, but once your system gets under a production load you’ll see the occasional exception.

“Fine,” you think, “I’ll just slap a ’synchronized’ around my use of that one, static instance.”

Ok, fine, you could do that and you’d be more or less ok, but the problem is that you’ve now taken a very common operation (date formatting and parsing) and crammed all of your otherwise-lovely, super-parallel application through a single pipe to get it done.

      

     大致意思:Tim Cull碰到一个SimpleDateFormat带来的严重的性能问题,该问题主要有SimpleDateFormat引发,创建一个SimpleDateFormat实例的开销比较昂贵,解析字符串时间时频繁创建生命周期短暂的实例导致性能低下。即使将SimpleDateFormat定义为静态类变量,貌似能解决这个问题,但是SimpleDateFormat是非线程安全的,同样存在问题,如果用‘synchronized’线程同步同样面临问题,同步导致性能下降(线程之间序列化的获取SimpleDateFormat实例)。

    Tim Cull使用Threadlocal解决了此问题,对于每个线程SimpleDateFormat不存在影响他们之间协作的状态,为每个线程创建一个SimpleDateFormat变量的拷贝或者叫做副本,代码如下:

 

Java代码 复制代码
  1. import java.text.DateFormat;   
  2. import java.text.ParseException;   
  3. import java.text.SimpleDateFormat;   
  4. import java.util.Date;   
  5. /**  
  6.  * 使用ThreadLocal以空间换时间解决SimpleDateFormat线程安全问题。  
  7.  * @author   
  8.  *  
  9.  */  
  10. public class DateUtil {   
  11.        
  12.     private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";   
  13.        
  14.     @SuppressWarnings("rawtypes")   
  15.     private static ThreadLocal threadLocal = new ThreadLocal() {   
  16.         protected synchronized Object initialValue() {   
  17.             return new SimpleDateFormat(DATE_FORMAT);   
  18.         }   
  19.     };   
  20.   
  21.     public static DateFormat getDateFormat() {   
  22.         return (DateFormat) threadLocal.get();   
  23.     }   
  24.   
  25.     public static Date parse(String textDate) throws ParseException {   
  26.         return getDateFormat().parse(textDate);   
  27.     }   
  28. }  
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * 使用ThreadLocal以空间换时间解决SimpleDateFormat线程安全问题。
 * @author 
 *
 */
public class DateUtil {
	
	private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
	
	@SuppressWarnings("rawtypes")
	private static ThreadLocal threadLocal = new ThreadLocal() {
		protected synchronized Object initialValue() {
			return new SimpleDateFormat(DATE_FORMAT);
		}
	};

	public static DateFormat getDateFormat() {
		return (DateFormat) threadLocal.get();
	}

	public static Date parse(String textDate) throws ParseException {
		return getDateFormat().parse(textDate);
	}
}

 

   创建一个ThreadLocal类变量,这里创建时用了一个匿名类,覆盖了initialValue方法,主要作用是创建时初始化实例。也可以采用下面方式创建;

 

Java代码 复制代码
  1. //第一次调用get将返回null   
  2. private static ThreadLocal threadLocal = new ThreadLocal();   
  3. //获取线程的变量副本,如果不覆盖initialValue,第一次get返回null,故需要初始化一个SimpleDateFormat,并set到threadLocal中   
  4. public static DateFormat getDateFormat()    
  5. {   
  6.     DateFormat df = (DateFormat) threadLocal.get();   
  7.     if(df==null){   
  8.         df = new SimpleDateFormat(DATE_FORMAT)   
  9.         threadLocal.set(df);   
  10.     }   
  11.     return df;   
  12. }  
//第一次调用get将返回null
private static ThreadLocal threadLocal = new ThreadLocal();
//获取线程的变量副本,如果不覆盖initialValue,第一次get返回null,故需要初始化一个SimpleDateFormat,并set到threadLocal中
public static DateFormat getDateFormat() 
{
	DateFormat df = (DateFormat) threadLocal.get();
	if(df==null){
		df = new SimpleDateFormat(DATE_FORMAT)
		threadLocal.set(df);
	}
	return df;
}

 

   我们看下我们覆盖的initialValue方法:

 

Java代码 复制代码
  1. protected T initialValue() {   
  2.         return null;//直接返回null   
  3.     }  

 

分享到:
评论

相关推荐

    java 简单的ThreadLocal示例

    在提供的"ThreadLocal示例"压缩包中,可能包含了一些具体的代码示例,展示如何在实际项目中运用ThreadLocal。通过查看这些示例,你可以更深入地理解ThreadLocal的工作方式以及如何在你的代码中有效地利用它。

    ThreadLocal应用示例及理解

    ### 示例:线程安全的计数器 假设我们需要一个线程安全的计数器,可以使用ThreadLocal实现: ```java public class ThreadLocalCounter { private static ThreadLocal<Integer> counter = new ThreadLocal(); ...

    ThreadLocal测试工程

    6. **代码示例**: ```java public class ThreadLocalExample { private static ThreadLocal<String> threadLocal = new ThreadLocal(); public static void main(String[] args) { new Thread(() -> { ...

    Quartz-ThreadLocal.rar

    这个压缩包 "Quartz-ThreadLocal.rar" 内含的学习资源很可能是关于如何在 Quartz 调度器中结合使用 ThreadLocal 的示例。 Quartz 的核心功能包括: 1. **作业与触发器**:在 Quartz 中,任务被称为“作业”(Job)...

    Android 详解ThreadLocal及InheritableThreadLocal

    在上述的示例中,我们看到ThreadLocal是如何在一个线程中设置值,并尝试在另一个线程中访问这个值的。当在主线程中设置了一个Person对象到ThreadLocal变量mThreadLocal后,主线程可以正常地获取到这个值。然而,在子...

    有关ThreadLocal的面试题你真的懂了吗

    6. ThreadLocal的使用示例:ThreadLocal可以用于保存线程上下文信息,例如每个请求的关联、事务管理等。下面是一个简单的示例代码: ```java public class ThreadLocalTest { private static ThreadLocal<Integer>...

    ThreadLocal

    #### 五、Java API中的ThreadLocal示例 下面的示例展示了一个更具体的场景——为每个线程分配一个唯一的标识符。 ```java import java.util.concurrent.atomic.AtomicInteger; public class ThreadId { // ...

    InheritableThreadLocal & ThreadLocal

    在这个示例中,我们创建了两个线程局部变量,一个是ThreadLocal,另一个是InheritableThreadLocal。在父线程中,我们分别为它们设置值,然后在子线程中获取。可以看到,子线程无法获取到ThreadLocal的值,但能成功...

    ThreadLocal简单Demo

    下面是一个简单的`ThreadLocal`使用示例: ```java public class ThreadLocalDemo { public static void main(String[] args) { ThreadLocal<String> threadLocal = new ThreadLocal(); // 在主线程中设置值 ...

    JAVA并发-自问自答学ThreadLocal.pdf

    - 示例代码展示了如何使用ThreadLocal来创建线程唯一的标识符。每个线程首次调用`UniqueThreadIdGenerator.getCurrentThreadId()`时,会分配一个唯一的ID,并将其保存在ThreadLocal中。之后的调用都会返回这个线程...

    正确理解ThreadLocal.pdf

    1. **数据库连接管理**:如上文的Hibernate示例,通过`ThreadLocal`管理每个线程的数据库连接,确保每个线程拥有独立的连接资源,避免了资源竞争。 2. **事务处理**:在事务管理中,`ThreadLocal`可以用于维护每个...

    Android 中 ThreadLocal使用示例

    在提供的示例代码中,MainActivity创建了一个ThreadLocal实例`mThreadLocal`。假设在主线程中设置了初始值,然后在两个子线程中分别设置不同的值。尽管三个线程都共享了同一个ThreadLocal对象,但每个线程通过`get()...

    事务的封装和Threadlocal实例

    下面是一个ThreadLocal的简单应用示例: ```java public class ConnectionHolder { private static final ThreadLocal<Connection> connectionHolder = new ThreadLocal(); public static void setConnection...

    ThreadLocal详解

    为了深入理解ThreadLocal的实现,我们可以构建一个简化的`SimpleThreadLocal`类示例,如代码清单1所示,其中包含了一个`Map`成员变量,用于存储线程及其对应的变量副本。 #### 结论 ThreadLocal作为一种独特的多...

    ThreadLocal简介_动力节点Java学院整理

    下面是一个使用ThreadLocal解决多线程并发问题的示例: public class SequenceB implements Sequence { private static ThreadLocal<Integer> numberContainer = new ThreadLocal() { @Override protected ...

    深入理解ThreadLocal工作原理及使用示例

    ThreadLocal的使用示例: ```java private ThreadLocal<Integer> tlA = new ThreadLocal(){ protected Integer initialValue(){ return 3; } }; ``` 在上面的示例中,我们定义了一个ThreadLocal对象,并复写了...

    java核心知识点学习----多线程间的数据共享和对象独立,ThreadLocal详解.pdf

    使用ThreadLocal的示例代码如下: ```java private static ThreadLocal<Integer> threadLocal = new ThreadLocal(); public void setData(int data) { threadLocal.set(data); } public int getData() { ...

    使用Java ThreadLocal.docx

    以下是一个完整的ThreadLocal示例,演示了如何在一个Runnable实例中使用ThreadLocal: ```java public class ThreadLocalExample { public static class MyRunnable implements Runnable { private ThreadLocal...

Global site tag (gtag.js) - Google Analytics