执行ResourceManager类中的main()方法后,可以清楚地看到:
第一种静态方式:大部分资源都能复用,但毫无规律;
第二种实例方式:即使是同一个线程,资源实例也不一样;
第三种ThreadLocal静态方式:相同的线程有相同的实例 。
结论是:ThreadLocal实现了线程的资源复用 。
也可以通过画图的方式来看清楚三者之间的不同:
这是静态方式下的资源管理:
文章插图
这是实例方式下的资源管理:
文章插图
这是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拿到了,就像这样:
文章插图
ThreadLocal在实际应用级开发中较少使用,因为容易造成OOM:
1、由于ThreadLocal是一个弱引用(WeakReference<ThreadLocal<?>>),因此会很容易被GC回收;
【4 Java多线程:ThreadLocal】2、但ThreadLocalMap的生命周期和Thread相同,这就会造成当key=null时,value却还存在,造成内存泄漏 。所以,使用完ThreadLocal后需要显式调用remove操作(但很多码农不知道这一点) 。
经验总结扩展阅读
- 飞机起飞前多久停止办理登机牌
- 夏天冰箱冷藏调多少度合适
- SpringCloud怎么迈向云原生?
- 大瓶矿泉水多少毫升
- 新鲜龙眼泡酒泡多久
- 西双版纳海拔多少米高
- 肾结石3mm需要治疗吗 肾结石3mm是多久形成的
- 烤箱烤烧饼上下火多少度不硬
- 生腌虾腌多久才能杀死寄生虫
- 华为freebuds4i使用方法_华为freebuds4i怎么重新配对