Home
JavaEE
Java GUI
Framework
DHtml
Android
插画
教程下载

ATOM 2.0   RSS 2.0
Add to iGoogle Add to Live.com
  • DeZender对用Zend Encoder加密过的PHP文件反编译
  • 写一个用于微博同步的Google Desktop Gadget
  • 在同学的QZone中看到的BB用药大全
  • 今天终于收到金山快盘的邀请码
  • 利用最短ie判断在不同浏览器上播放背景音乐
  • 对插画方面的一点感受与回忆
  • 网上看到的两个死里逃生的图片,记录一下
  • 今天开通了糖果社区,附几个激活码
  • 终于可以实现我的多个微博实时同步了
  • 备案和现场拍照就是对站长们的瞎折腾
  • 今天开通了糖果社区,附几个激活码
  • 终于可以实现我的多个微博实时同步了
  • 备案和现场拍照就是对站长们的瞎折腾
  • 昨天借用飞姐的佳作做的一个浪漫爱情网页
  • 有几个腾讯微博的邀请码(实时更新)
  • BB的网站移到了GAE-JAVA上了
  • 一个基于GAE Python Web.py和JQuery的留言本程序
  • 类许愿墙的一个告白网站和一个电子书网站
  • Android中用Bitmap获取图片中某个区域的图象
  • 对暴力破解带密码的QQ相册的可行性分析
  • 对淘宝web旺旺版一些通讯接口的研究

java.lang.ThreadLocal

posted by David Chen at July 3, 2007, 3:24 AM    

早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编

写多线程程序时提供了一种新的选择。使用这个工具类可以很简洁地编写出优美的多线程程序,虽然

ThreadLocal非常有用,但是似乎现在了解它、使用它的朋友还不多。

  ThreadLocal是什么

  ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread

,而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程

局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值

的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度

看,就好像每一个线程都完全拥有该变量。线程局部变量并不是Java的新发明,在其它的一些语言

编译器实现(如IBM XL FORTRAN)中,它在语言的层次提供了直接的支持。因为Java中没有提供在语

言层次的直接支持,而是提供了一个ThreadLocal的类来提供支持,所以,在Java中编写线程局部变

量的代码相对比较笨拙,这也许是线程局部变量没有在Java中得到很好的普及的一个原因吧。

  ThreadLocal的设计

  首先看看ThreadLocal的接口:

  Object get() ; // 返回当前线程的线程局部变量副本 protected Object initialValue(); //

返回该线程局部变量的当前线程的初始值void set(Object value); // 设置当前线程的线程局部变

量副本的值

  ThreadLocal有3个方法,其中值得注意的是initialValue(),该方法是一个protected的方法,

显然是为了子类重写而特意实现的。该方法返回当前线程在该线程局部变量的初始值,这个方法是一

个延迟调用方法,在一个线程第1次调用get()或者set(Object)时才执行,并且仅执行1次。

ThreadLocal中的确实实现直接返回一个null:

protected Object initialValue() { return null; }
 


  ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在

ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。比如下面的示例实现:

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;
 }
}
 


  当然,这并不是一个工业强度的实现,但JDK中的ThreadLocal的实现总体思路也类似于此。

  ThreadLocal的使用

  如果希望线程局部变量初始化其它值,那么需要自己实现ThreadLocal的子类并重写该方法,通

常使用一个内部 匿名类对ThreadLocal进行子类化,比如下面的例子,SerialNum类为每一个类分配

一个序号:

public class SerialNum
{
 // The next serial number to be assigned

 private static int nextSerialNum = 0;
 private static ThreadLocal serialNum = new ThreadLocal()
 {
  protected synchronized Object initialValue()
  {
   return new Integer(nextSerialNum++);
  }
 };

 public static int get()
 {
  return ((Integer) (serialNum.get())).intValue();
 }
}
 


  SerialNum类的使用将非常地简单,因为get()方法是static的,所以在需要获取当前线程的序号

时,简单地调用:

int serial = SerialNum.get();
 


  即可。

  在线程是活动的并且ThreadLocal对象是可访问的时,该线程就持有一个到该线程局部变量副本

的隐含引用,当该线程运行结束后,该线程拥有的所以线程局部变量的副本都将失效,并等待垃圾收

集器收集。

  ThreadLocal与其它同步机制的比较

  ThreadLocal和其它同步机制相比有什么优势呢?ThreadLocal和其它所有的同步机制都是为了解

决多线程中的对同一变量的访问冲突,在普通的同步机制中,是通过对象加锁来实现多个线程对同一

变量的安全访问的。这时该变量是多个线程共享的,使用这种同步机制需要很细致地分析在什么时候

对变量进行 读写,什么时候需要锁定某个对象,什么时候释放该对象的锁等等很多。所有这些都是

因为多个线程共享了资源造成的。ThreadLocal就从另一个角度来解决多线程的并发访问,

ThreadLocal会为每一个线程维护一个和该线程绑定的变量的副本,从而隔离了多个线程的数据,每

一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程

安全的共享对象,在编写多线程代码时,可以把不安全的整个 变量封装进ThreadLocal,或者把该对

象的特定于线程的状态封装进ThreadLocal。

  由于ThreadLocal中可以持有任何类型的对象,所以使用ThreadLocal get当前线程的值是需要进

行强制类型转换。但随着新的Java版本(1.5)将模版的引入,新的支持模版参数的

ThreadLocal<T>

类将从中受益。也可以减少强制类型转换,并将一些错误检查提前到了编译期,将一定程度地简化

ThreadLocal的使用。

  总结

  当然ThreadLocal并不能替代同步机制,两者面向的问题领域不同。同步机制是为了同步多个线

程对相同资源的并发访问,是为了多个线程之间进行通信的有效方式;而ThreadLocal是隔离多个线

程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样当然不需要对多个线程进行同

步了。所以,如果你需要进行多个线程之间进行通信,则使用同步机制;如果需要隔离多个线程之间

的共享冲突,可以使用ThreadLocal,这将极大地简化你的程序,使程序更加易读、简洁。
Labels:
Trackback:   http://cwq.iou1314.com/_a139
微博最近更新
[2010-09-06 16:08]    明天有市领导来,后天又有省领导来,今天一个下午就拉了5条大横幅,累死我了,上周星期6,7办公室都要上班,这种生活什么时候可以摆脱?
[2010-09-04 04:43]    又是要加班的双休日,昨晚和领导去县城做资料做到11:30,确定这两天都要加班,刚准备回家,跟着领导接 电话说有村民想自杀不成,已带到卫生院,又跟领导回乡镇处理劝说一下。搞完到了1:30。回来凉都冲就睡 觉了。
本站内的任何文章,只代表个人意见或学习所用,如有版权声明,请尊重作者的劳动成果,在转载时请保留原始链接并注明出处。
Power by David's PhpCms, © 2007 - 2010 CWQ.IOU1314.COM All Rights Reserved.