posts - 60,comments - 71,trackbacks - 0

什么是ThreadLocal

ThreadLocal并不能从字面上理解为线程的本地实现版本,因为它并不是一个线程,而是ThreadLocal Variable(线程局部变量)。它的功能非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,使得每一个线程都可以独立地改变自己的副本,而不会和其他线程珠副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。
首先看看ThreadLocal的方法:
1、get()
  返回当前线程的线程局部变量的副本,当第一次调用这个方法时会自动创建并且初始化一个线程局部变量的副本。
2、initialValue()
  返回该线程的线程局部变量的当前线程的初始值,这个方法只在第一次调用get()方法的时候被调用一次。如果在调用get()方法之前已经调用了set()方法,那么这个方法将不会被调用。
这个方法是一个protected的方法,不能直接调用该方法,只有在其子类中将该方法重写才能改变它的行为。在默认情况下,该方法的返回值为null。
3、set()
  设置当前线程的线程局部变量副本的值。大多数的应用程序都不需要调用这个方法,可以通过initialValue()方法来设置当前线程局部变量的值。
4、remove()
  移除当前线程局部变量的值。这样做的目的是可以降低当前线程的存储空间的使用量,这是Java1.5的新增方法。

ThreadLocal的使用
ThreadLocal的使用方法有两种,一种方法是自己实现ThreadLocal的子类,并重写initialValue()方法。另一种方法是定义一个表态的ThreadLocal实例,通过使用set()方法来初始化这个线程局部变量的值。
  如果希望线程局部变量初始化的时候就具有值,那么需要自己实现ThreadLocal的子类并重写该方法,通常使用一个内部匿名类对ThreadLocal进行子类化。例如在下面的例子中,SerialNum类为每一个类分配一个序号:
程序代码 程序代码
public class SerialNum
{
 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();
 }
}

同样,也可以不采用实现ThreadLocal子类的方法来实现同样的功能,如下所示:
程序代码 程序代码
public class SerialNum1
{
 private static int nextSerialNum=0;
 private static ThreadLocal serialNum=new ThreadLocal();
 public static int get()
 {
  if(serialNum.get()==null)
   serialNum.set(new Integer(nextSerialNum++));
  return ((Integer)(serialNum.get())).intValue();
 }

}

  SerialNum类的使用非常简单,因为get()方法是static的,所以在需要获取当前线程的序号时,简单地调用int serial=SerialNum.get();即可。
  在线程是活动并且ThreadLocal对象是可访问时,该线程就持有一个到该线程局部变量副本的隐含引用。当该线程运行结束后,该线程拥有的所有线程局部变量的副本都将失效,并等待垃圾收集器收集。

  ThreadLocal 几点作用:
1)可以启到类似单态类的作用,实际上是要使某变量达到线程安全时,可以使用这种方式;
2)可以结合HttpServletRequest,HttpServletResponse,ServletContext等来实现使用运行时数据;

在使用ThreadLocal 时一般是使用get()方法,但在使用这个方法时,会先调用set()方法,具体的用途可以在创建ThreadLocal 变量时指定,也可以

重写set()方法,如果不想设定set()方法,可以在创建ThreadLocal 变量时指定,如下:

private static ThreadLocal currentUser = new ThreadLocal(){
         
protected synchronized Object initialValue() {
                 
return new User();
         }

     }
;

或者使用:public static void setCurrentUser(User user) { currentUser.set(user); }手工给ThreadLocal 变量赋值(user),
要获得User对象时,可以使用 User u = (User)currentUser.get();即直接调用get()方法,来返回set()方法所设置的值(也可以不写
此方法,而直接在定义变量时,重写initialValue()方法,此方法返回所要设置的值或对象),这里是User对象,然后调用User类的其他方法.


 
posted on 2008-05-04 20:37 henry1451 阅读(1318) 评论(0)  编辑  收藏 所属分类: Java技术

只有注册用户登录后才能发表评论。


网站导航: