执行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回收;
2、但ThreadLocalMap的生命周期和Thread相同,这就会造成当key=null时,value却还存在,造成内存泄漏 。所以,使用完ThreadLocal后需要显式调用remove操作(但很多码农不知道这一点) 。
推荐阅读
- SpringCloud怎么迈向云原生?
- 华为freebuds4i使用方法_华为freebuds4i怎么重新配对
- DNF如何升冒险团等级(dnf冒险团40级要多少号)
- javascript编程单线程之异步模式Asynchronous
- Java 8 Time API
- 3050和3050ti的差距_3050和3050ti差多少
- 多可用区 亚马逊云 RDB数据故障转移
- realmev11多少钱_真我v11手机多少钱
- 洛克王国雪顶妖兽进化概率是多少
- vivox60pro+支持无线充电吗_vivox60pro+电池容量是多少