java.lang.ThreadLocal类的用法,及与同步机制的比较

一、ThreadLocal类

     ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。线程局部变量并不是Java的新发明,在其它的一些语言编译器实现(如IBM XL FORTRAN)中,它在语言的层次提供了直接的支持。因为Java中没有提供在语言层次的直接支持,而是提供了一个ThreadLocal的类来提供支持,所以,在Java中编写线程局部变量的代码相对比较笨拙,这也许是线程局部变量没有在Java中得到很好的普及的一个原因吧。

    举例:

1、类SeriaNum类为每一个线程创建一个唯一的序列号,在线程生命周期内不变。

public class SerialNum {
    // The next serial number to be assigned
    private static int nextSerialNum = 0;

    @SuppressWarnings("unchecked")
private static ThreadLocal serialNum = new ThreadLocal() {
        protected synchronized Object initialValue() {
            return new Integer(nextSerialNum++);
        }
    };

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

2、测试

public class thred extends Thread{
private int num;
public void run(){ 
   num=SerialNum.get();
   System.out.println(SerialNum.get());
}
public static void main(String[] args) {
   thred a=new thred();
   thred b=new thred();
   thred c=new thred();
   thred d=new thred();
   thred e=new thred();
   thred f=new thred();
   thred g=new thred();
   a.start();
   b.start();
   c.start();
   d.start();
   e.start();
   f.start();
   g.start();
   try {
    sleep(10000);
   } catch (InterruptedException e1) {
    e1.printStackTrace();
   }
   System.out.println(b.num);
}
}

输出:

0
1
2
3
4
5
6
结论:可以看书abcdefg六个线程的序列号确定了后,不在变化。

二、 ThreadLocal与其它同步机制的比较

   ThreadLocal和其它同步机制相比有什么优势呢?ThreadLocal和其它所有的同步机制都是为了解决多线程中的对同一变量的访问冲突,在普通的同步机制中,是通过对象加锁来实现多个线程对同一变量的安全访问的。这时该变量是多个线程共享的,使用这种同步机制需要很细致地分析在什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放该对象的锁等等很多。所有这些都是因为多个线程共享了资源造成的。ThreadLocal就从另一个角度来解决多线程的并发访问,ThreadLocal会为每一个线程维护一个和该线程绑定的变量的副本,从而隔离了多个线程的数据,每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的整个变量封装进ThreadLocal,或者把该对象的特定于线程的状态封装进ThreadLocal。

       由于ThreadLocal中可以持有任何类型的对象,所以使用ThreadLocal get当前线程的值是需要进行强制类型转换。但随着新的Java版本(1.5)将模版的引入,新的支持模版参数的ThreadLocal类将从中受益。也可以减少强制类型转换,并将一些错误检查提前到了编译期,将一定程度地简化ThreadLocal的使用。


你可能感兴趣的:(java.lang.ThreadLocal类的用法,及与同步机制的比较)