Java ThreadLocal使用浅析

来源:互联网 发布:xampp mysql登陆 编辑:程序博客网 时间:2024/05/18 20:46

Java ThreadLocal使用浅析

 

 

JAVA API 文档里关于 ThreadLocal 的定义是:

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

这个类提供了一个线程本地的变量。这些变量在被共享访问的情况下在不同的线程里是独立的 ( 必须通过get  set 方法来访问 ) 

 

很显然该类提供了一个机制可以防止多线程访问带来的不安全机制。实际上就是在线程本地保存一个变量,而不是通过共享变量。这个就要看我们的使用场合了,如果我们确实需要共享的数据,那还是必须通过同步机制来保证数据的安全。如果有些情况希望不同的线程保存的变量各自分开,那用这个还是比较合适的。

ThreadLocal 这个类本身不是代表线程要访问的变量,这个类的成员变量才是。 JDK1.5  ThreadLocal加了泛型功能,即是 ThreadLocal<T>, 这个泛型 T 即是要线程的本地变量。线程通过 ThreadLocal  get set 方法去访问这个变量 T  ThreadLocal 提供了一个机制,它能保证线程通过这个来访问它来访问类型为 T的变量的时候是不同的拷贝。所以访问该变量必须通过 Threadlocal 这个类只提供了两个 public 方法,即是get()  set ()方法来访问。

同时还提供了一个 inintValue()  protected 方法。该方法用来初始化变量值。

注意 默认情况下 initValue(), 返回 null 。线程在没有调用 set 之前,第一次调用 get 的时候,get 方法会默认去调用 initValue 这个方法。所以如果没有覆写这个方法,可能导致 get 返回的是 null 。当然如果调用过 set 就不会有这种情况了。但是往往在多线程情况下我们不能保证每个线程的在调用 get 之前都调用了 set ,所以最好对 initValue 进行覆写,以免导致空指针异常。

说了这么多,估计还不如看下例子吧,下面还是上例子。

例子 1 :没有使用 Threadlocal 的情况:

/**

*

* @author yblin

* 2009.8.18

*

*/

public class TestWithNoThreadLocal {

public static int a = 0;


public static void main(String[] args) {

MyThread myThread = new MyThread();

myThread.start();

for ( int i = 0; i < 5; i++) {

a = a + 1;

System. out .println(Thread. currentThread ().getName() + ":" + a );

}

}

public static class MyThread extends Thread {

public void run() {

for ( int i = 0; i < 5; i++) {

a = a + 1;

System. out .println(Thread. currentThread ().getName() + ":" + a );

}

}

}


}


运行的一种结果如下:

main:2

Thread-0:2

main:3

Thread-0:4

main:5

Thread-0:6

main:7

Thread-0:8

main:9

Thread-0:10


在没有同步的机制下,该结果有不安全的情况发生是正常的,两个线程都得到 2 。下面请看用了ThreadLocal 的效果。


例子 2 :使用了 Threadlocal 的情况:

/**

*

* @author yblin

* 2009.8.18

*

*/

public class TestThreadLocal2 {

private static ThreadLocal<Integer> a = new ThreadLocal<Integer>() {

public Integer initialValue() { // 初始化,默认是返回 null

return 0;

}

};


public static void main(String args[]) {

MyThread my;

my = new MyThread();

my.start();

for ( int i = 0; i < 5; i++) {

a .set( a .get() + 1);

System. out .println(Thread. currentThread ().getName() + ":" + a .get());

}

}


public static class MyThread extends Thread {

public void run() {

for ( int i = 0; i < 5; i++) {

a .set( a .get() + 1);

System. out .println(Thread. currentThread ().getName() + ":"

+ a .get());

}

}

}

}


运行的一种结果如下:

main:1

Thread-0:1

main:2

Thread-0:2

main:3

Thread-0:3

main:4

Thread-0:4

Thread-0:5

main:5


如上是关于 ThreadLocal 的简单介绍。其内部具体实现可看其类实现。

 

转载于:http://blog.csdn.net/abing37/article/details/4460298

0 0