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

理解ThreadLocal的涵义

阅读更多

自从碰到N多个性能问题后,看是注意使用ThreadLocal的使用,本章只是体现如何使用ThreadLocal,ThreadLocal在性能方面的提高以及在内存分配方面的优势不再讨论范围内。

ThreadLocal的扼要

一个线程有它独立的流程的stack,在web的应用容器中都有Thread Pool,因为线程的创建都是重量级的消耗。

weblogic、glassfish、jboss都是允许你调解Pool。

需要了解ThreadLocal,那先假设我们自己订制一个简单的ThreadLocal

import java.util.HashMap;
import java.util.Map;

public class CustomThreadLocal {

 private static Map threadMap = new HashMap();

 public static void add(Object object) {
  threadMap.put(Thread.currentThread(), object);
 }

 public static void remove(Object object) {
  threadMap.remove(Thread.currentThread());
 }

 public static Object get() {
  return threadMap.get(Thread.currentThread());
 }

}

 

public class ThreadContext {

 private String userId;

 private Long transactionId;

 public String getUserId() {
  return userId;
 }

 public void setUserId(String userId) {
  this.userId = userId;
 }

 public Long getTransactionId() {
  return transactionId;
 }

 public void setTransactionId(Long transactionId) {
  this.transactionId = transactionId;
 }

 public String toString() {
  return 'userId:' + userId + ',transactionId:' + transactionId;
 }

}

 

 

public class ThreadLocalMainSampleEx1 {

 public static void main(String[] args) {
  new Thread(new Runnable() {
   public void run() {
    ThreadContext threadContext = new ThreadContext();
    threadContext.setTransactionId(1l);
    threadContext.setUserId('User 1');
    CustomThreadLocal.add(threadContext);
    //here we call a method where the thread context is not passed as parameter
    PrintThreadContextValues.printThreadContextValues();
   }
  }).start();
  new Thread(new Runnable() {
   public void run() {
    ThreadContext threadContext = new ThreadContext();
    threadContext.setTransactionId(2l);
    threadContext.setUserId('User 2');
    CustomThreadLocal.add(threadContext);
    //here we call a method where the thread context is not passed as parameter
    PrintThreadContextValues.printThreadContextValues();
   }
  }).start();
 }
}

 当我CustomThreadLocal.get()时候,它使用通过内部map去寻找到它自身独有Context上下文信息。

那如果采纳使用ThreadLocal呢?

public class ThreadContext {

 private String userId;
 private Long transactionId;

 private static ThreadLocal threadLocal = new ThreadLocal(){
  @Override
        protected ThreadContext initialValue() {
            return new ThreadContext();
        }

 };
 public static ThreadContext get() {
  return threadLocal.get();
 }
 public String getUserId() {
  return userId;
 }
 public void setUserId(String userId) {
  this.userId = userId;
 }
 public Long getTransactionId() {
  return transactionId;
 }
 public void setTransactionId(Long transactionId) {
  this.transactionId = transactionId;
 }

 public String toString() {
  return 'userId:' + userId + ',transactionId:' + transactionId;
 }
}

 是不是挺简单的使用的呢?如果配置上Pool,是不是挺完美的,在N多框架中都基本上采用上述方式,ibatis、BoneCP等都是携带

 

ThreadLocal另外用处是对于非线程安全的实例,通过ThreadLocal的包装同样能够保证并发下的安全。

package ccs.progest.javacodesamples.threadlocal.ex4;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadLocalDateFormat {
 // SimpleDateFormat is not thread-safe, so each thread will have one
 private static final ThreadLocal formatter = new ThreadLocal() {
  @Override
  protected SimpleDateFormat initialValue() {
   return new SimpleDateFormat('MM/dd/yyyy');
  }
 };
 public String formatIt(Date date) {
  return formatter.get().format(date);
 }
}

 ThreadLocal的应用场景

1.类似于userId、tractionId、以及session等

2.为了保证每个线程更好独享自己实例信息

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics