一、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对象来实现,如果发现了一个对象还有续引用,就会在垃圾回收之前,把这个类的续引用加入到与之关联的引用对象中。