<%@ page contentType="text/html; charset=gb2312"%> Java中ThreadLocal的设计与使用
网站公告:   ◆北天JAVA技术网热情为java爱好者服务,本网内容包括JAVA(JSP、servlet、EJB、webservice、j2ee、javabean、应用服务器、JavaScript),数据库(MYSQL、SQL Server、Sybase、Oracle、DB2、数据库综合知识),设计研究(设计模式、Struts、Spring、Hibernate、设计框架、设计综合知识),WEB2.0新技术(主要介绍AJAX),以及各种技术的入门、实例、例子等等,欢迎各位多来坐坐!◆  诚邀各位JAVA爱好者加盟!◆  本网站内容丰富,更新快,保证每周20篇以上!  
加入收藏
设为首页
联系站长
承接项目
  相关资源:网站首页 | 免费培训学院 | 技术论坛 | JAVA聊天室 | 作家专栏 | 开发工具 | 认证考试 | 会员俱乐部
  JAVA技术初学者园地 | jsp与servlet | javascript | Java源代码 | EJB | web service | 应用服务器 | JAVA综合知识
  设计研究设计模式 | 设计框架 | Struts | Spring | Hibernate | 开源项目 | 面向对象设计 | 设计综合知识
  数 据 库MYSQL | SQL Server | Sybase | Oracle | DB2 | Informix | Access | 数据库综合知识
  其他资源:AJAX新技术 | 网站开发 | ERP软件 | OA办公软件 | 商业智能BI | 开发综合知识 | 承接项目 | 项目试用

 
 
Java中ThreadLocal的设计与使用
     发布者: 发布时间:2007-09-23
早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.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类将从中受益。也可以减少强制类型转换,并将一些错误检查提前到了编译期,将一定程度地简化ThreadLocal的使用。

总结

当然ThreadLocal并不能替代同步机制,两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行通信的有效方式;而ThreadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样当然不需要对多个线程进行同步了。所以,如果你需要进行多个线程之间进行通信,则使用同步机制;如果需要隔离多个线程之间的共享冲突,可以使用ThreadLocal,这将极大地简化你的程序,使程序更加易读、简洁。
(转载文章请保留出处:北天JAVA技术网(www.java114.com))
 
更多精彩文章:
Java程序开发中如何应用线程
Sun授权ASEC-Java培训中心
品一杯美味的咖啡:Sun公司认证
SCJP Mock Exam 4
SCJP Mock Exam 3
SCJP Mock Exam 2
 
最近评论:
        
鍥炲
        
那个雨天的想法!
wow gold,wow power leveling.wow power leveling,wow power leveling, max(2709)
        
如果真的有来生!
四川旅游,九寨沟旅游,稻城亚丁旅游,四姑娘山旅游,海螺沟旅游,西藏旅游, max(4095)
        
那天的情景!
Maple Story mesos,MapleStory mesos,ms mesos,mesos,SilkRoad Gold, max(6849)
        
轻轻走过你的窗前!
world of warcraft gold,cheap world of warcraft gold,warcraft gold,world of warcraft gold,cheap world of warcraft gold,warcraft gold max(2728)
        
不在的哪天!
final fantasy xi gil,final fantasy xi gil,final fantasy xi gil,final fantasy xi gil, max(9353)
        
昨夜的狂想曲!
wow gold,WoW Gold,world of warcraft gold,WoW Gold, max(5881)
        
没有情人的情人节!
wow gold,wow power leveling.wow power leveling,wow power leveling, max(5522)
        
回复:Java中ThreadLocal的设计与使用
power leveling world of warcraft gold power leveling wow wow gold buy wow gold wow power leveling guild wars gold Maple Mesos guild wars money cheap Maple Story Mesos buy Maple Meso gw money cheap guild wars money cheap gw money Maple Story Meso cheap MapleStory Mesos runescape money runescape coin runescape gold runescape power leveling buy runescape gold rs gold runescape gold runescape gp
        
远方的你!
world of warcraft gold,wow gold,a href="http://www.gogoer.com">world of warcraft gold,cheap world of warcraft gold max(3037)
        
标 题:   
内 容:   
 
                                  
 
免责声明:该文章由网友发表,如果对您造成侵权,请联系站长

首页 - 承接项目 - 网站地图 - 联系我们 -
版权所有北天JAVA技术工作室 ICP证号:粤ICP备06079815号