ThreadLocal 学习

关于ThreadLocal的用法在进行了诸多的研究分析之后,终于有所斩获,掌握了其本质的若干用法,先总结如下:

在对运行同一段代码的多线程程序中,用以实现同一个线程之内同一个变量的同步,避免其多个线程之间彼此的干扰。效率相对于synchronized而言,有相当的提升。
本质上讲,其就是实现单一线程的私有变量
关于其实现,摘引klyuan(javaeye)上的例子,如下,很好的说明了ThreadLocal的实现方式,当然你也可以参考JDK源代码中的实现。本质上,其就是一个同步的HashMap而已,可以为线程,value为所定义的局部变量。

public class ThreadLocal
{
 private Map values = Collections.synchronizedMap(new HashMap());
 public Object get()
 {
  Thread curThread = Thread.currentThread();
  Object o = values.get(curThread);
  if (o == null && !values.containsKey(curThread))
  {
   o = initialValue();
   values.put(curThread, o);
  }
  return o;
 }

 public void set(Object newValue)
 {
  values.put(Thread.currentThread(), newValue);
 }

 public Object initialValue()
 {
  return null;
 }
}
应用分析,一个同事将一段代码给我,说其中关于ThreadLocal的set(null)这行代码,如果注释掉,会出现什么情况,详细代码如下:

我们可以看到有2行关于local和local_tr的set(null)的方法如果被注释掉的情况,我们可以推测会出现什么样的情况。

/**
* Import Package missing for space
**/
public class HibernateUtil {
private static SessionFactory sf;
private static ThreadLocal local = new ThreadLocal();
private static ThreadLocal local_tr = new ThreadLocal();

static{
Configuration conf = new Configuration();
conf = conf.configure("/hibernate.cfg.xml");
sf = conf.buildSessionFactory();
}

public static Session getSession(){
System.out.println("threadLocalid=="+local);
Session session = null;
if(local.get()==null){
session = sf.openSession();
System.out.println("---------session is created------------");
local.set(session);
}else{
session = (Session)local.get();
}
return session;
}

public static void begin(){
Session session = (Session)local.get();
Transaction ts = null;
if(local_tr.get()==null){
ts = session.beginTransaction();
local_tr.set(ts);
}
}

public static void commit(){
Transaction tr = (Transaction)local_tr.get();
tr.commit();
local_tr.set(null); // this line is removed,then what will happen?
System.out.println("---------transaction is commited------------");
}

public static void rollback(){
Transaction tr = (Transaction)local_tr.get();
tr.rollback();
System.out.println("---------transaction is rollbacked------------");
}

public static void close(){
Session session = (Session)local.get();
if(session!=null){
session.close();
System.out.println("---------session is destroyed------------");
}
local.set(null); // this line is removed, then what will happen?
}
}



如果基于local(Session的局部变量)不进行set(null)的话,会出现所有的thread都基于获取同一个session的情况。

如果local_tr(Transaction的局部变量)不进行set(null)的话,对于基于同一个session的线程而言,其只可以进行一次的事务提交,后续都将无法进行,因为每次进行之前会进行局部变量的有效判断。

总结: ThreadLocal是一个有效的多线程局部变量工具,当然也是一把双刃剑,用好的话可以制敌,反之则可能祸己。要用好ThreadLocal,我们只需记住其本质:线程局部变量;其实现的本质是一个基于同步的HashMap就可以了。每一个线程都是用于该变量的一个独立副本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值