一、ThreadLocal使用
public class ThreadLocalApp {
public static void main(String[] args) {
Number t1 = new Number();
Number t2 = new Number();
Number t3 = new Number();
t1.start();
t2.start();
t3.start();
}
}
public class Number extends Thread{
private int num = 0;;
public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
protected Integer initialValue() {
return 0;
};
};
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(getName() + ",number:" + getNumber());
}
}
private String getNumber() {
num = threadLocal.get() + 1;
threadLocal.set(num);
return num + "";
}
}
运行结果如下:
二、ThreadLocal的使用场景
如果需要创建一个全局变量,每个线程需要有各自的一个副本,并且每个线程之间互不影响,这时候就可以使用ThreadLocal。
三、ThreadLocal的实现原理
ThreadLocal的底层实现为Map,key为当前线程对象(Thread.currentThread()),value为当前全局共享变量的副本值。
ThreadLocal里面使用了一个弱引用,当释放掉强引用之后,map里面的value没有被回收,而这块value永远不会被访问到了,存在内存泄漏,最好的做法是调用ThreadLocal的remove方法。
在ThreadLocal的生命周期中,都存在这些引用,实线代表强引用,虚线代表弱引用。
每个thread中都存在一个map,map的类型是ThreadLocal.ThreadlocalMap,Map中的key为一个ThreadLocal的实例,这个map使用了弱引用,弱引用针对key。
四、Java的四种引用说明
1、强引用:例如:Object obj = new Object();垃圾回收器绝不会回收它;
2、软引用:通过SoftReference类来实现的,一旦发现了软引用的对象,如果内存空间足够,则不会回收它,如果内存空间不足,则会回收;
3、弱引用:通过weakReference类来实现,一旦发现了弱引用的对象,不管当前内存空间是否足够,都会回收;
4、幽灵引用(虚引用):PhantomReference对象来实现,如果发现了一个对象还有续引用,就会在垃圾回收之前,把这个类的续引用加入到与之关联的引用对象中。