再了解ThreadLocal之前先看一个简单的Java线程示例。
线程类:
public class TestThread2 extends Thread {
int a;
String b = "a";
@Override
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println(Thread.currentThread().getName() + " " + a + " "
+ b);
a++;
b = "" +(char)(b.charAt(0)+1);
}
}
}
主测试类代码:
public class MainTest {
public static void main(String[] args) {
Runnable test = new TestThread2();
Thread a1 = new Thread(test,"线程1");
Thread a2 = new Thread(test,"线程2");
Thread a3 = new Thread(test,"线程3");
//a1,a2,a3共享test对象的实例变量
a1.start();
a2.start();
a3.start();
}
}
某个输出结果为:
线程1 10 a 线程1 11 b 线程1 12 c 线程2 13 d 线程3 14 e 线程2 14 e 线程2 15 f 线程3 17 g 线程3 18 h
由结果可以看到,test对象里的a,b变量被几个线程共享,所以他们的结果累加了。当然如果改变一种写法,几个线程不通过test对象创建,则不构成共享对象,那么几个都只用自己的成员变量,结果就会不一样了。代码:
public class MainTest {
public static void main(String[] args) {
//Runnable test = new TestThread2();
Thread a1 = new Thread(new TestThread2(),"线程1");
Thread a2 = new Thread(new TestThread2(),"线程2");
Thread a3 = new Thread(new TestThread2(),"线程3");
// Thread a1 = new TestThread2();
// Thread a2 = new TestThread2();
// Thread a3 = new TestThread2();
a1.start();
a2.start();
a3.start();
}
}
运行结果为:
线程1 0 a
线程3 0 a
线程1 1 b
线程1 2 c
线程3 1 b
线程3 2 c
线程2 0 a
线程2 1 b
线程2 2 c
好了,现在的问题就是能不能让共享的对象里的变量也有上面等效的结果,每个对象都把共享的对象属性处理成自己的局部变量。ThreadLocal就是用来达到这个目的的。更改线程类代码为:
public class TestThread2 extends Thread {
private static ThreadLocal<Integer> a = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
private static ThreadLocal<String> b = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return "a";
}
};
@Override
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println(Thread.currentThread().getName() + " " + a.get()
+ " " + b.get());
a.set(a.get() + 1);
b.set("" + (char) (b.get().charAt(0) + 1));
}
}
}
再次运行共享test对象的主程序测试类,打印结果如下:
线程1 0 a 线程2 0 a 线程2 1 b 线程2 2 c 线程3 0 a 线程3 1 b 线程3 2 c 线程1 1 b 线程1 2 c
对于ThreadLocal的一般解释:
ThreadLocal类位于java.lang下,即java.lang.ThreadLocal,对于这个类的解读和实现分析,网上已经有不少了:
http://sishuok.com/forum/blogPost/list/340.html
http://blog.youkuaiyun.com/qjyong/article/details/2158097
http://lavasoft.blog.51cto.com/62575/51926/
http://my.oschina.net/lichhao/blog/111362
http://www.iteye.com/topic/103804
用自己的话再解释一下:
每个java.lang.Thread线程类里都有一个ThreadLocalMap成员属性(打开源码就能看见):
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocalMap是ThreadLocal的静态内部类。Thread里的这个threadLocals成员属性就是用来存储各个ThreadLocal的key-value映射的。这里的key就是ThreadLocal对象,值就是ThreadLocal里设定的值。拿上面的代码线程类为例:线程a1中的threadLocals存储了两个key-value对,一个是a(ThreadLocal型)-0(int型),另一个是b(ThreadLocal型)-"a"(字符串型)。线程a2,a3同理。