4 Java多线程:ThreadLocal( 二 )

执行ResourceManager类中的main()方法后,可以清楚地看到:
第一种静态方式:大部分资源都能复用,但毫无规律;
第二种实例方式:即使是同一个线程,资源实例也不一样;
第三种ThreadLocal静态方式:相同的线程有相同的实例 。
结论是:ThreadLocal实现了线程的资源复用 。
也可以通过画图的方式来看清楚三者之间的不同:
这是静态方式下的资源管理:

4 Java多线程:ThreadLocal

文章插图
这是实例方式下的资源管理:
4 Java多线程:ThreadLocal

文章插图
这是ThreadLocal静态方式下的资源管理:
4 Java多线程:ThreadLocal

文章插图
理解了之后,再来看一个数据传递的例子,也就是ThreadLocal实现线程间通信的例子:
/** * 数据传递 * * @author 湘王 */public class DataDeliver {    static class Data1 {        public void process() {            Resource resource = new Resource("xiangwang", "123456");            //将对象存储到ThreadLocal            ResourceContextHolder.holder.set(resource);            new Data2().process();        }    }    static class Data2 {        public void process() {            Resource resource = ResourceContextHolder.holder.get();            System.out.println("Data2拿到数据: " + resource.getName());            new Data3().process();        }    }    static class Data3 {        public void process() {            Resource resource = ResourceContextHolder.holder.get();            System.out.println("Data3拿到数据: " + resource.getName());        }    }    static class ResourceContextHolder {        public static ThreadLocal<Resource> holder = new ThreadLocal<>();    }    public static void main(String[] args) {        new Data1().process();    }}运行代码之后,可以看到Data1的数据都被Data2和Data3拿到了,就像这样:
4 Java多线程:ThreadLocal

文章插图
ThreadLocal在实际应用级开发中较少使用,因为容易造成OOM:
1、由于ThreadLocal是一个弱引用(WeakReference<ThreadLocal<?>>),因此会很容易被GC回收;
【4 Java多线程:ThreadLocal】2、但ThreadLocalMap的生命周期和Thread相同,这就会造成当key=null时,value却还存在,造成内存泄漏 。所以,使用完ThreadLocal后需要显式调用remove操作(但很多码农不知道这一点) 。

经验总结扩展阅读