ThreadLocale理解和对WeakReference的运用
来源:互联网 发布:百分百网络营销软件 编辑:程序博客网 时间:2024/05/16 14:43
理论基础看其他收录的文章,这里记录的是自己的理解。 每个Thread都有一个成员变量ThreadLocal.ThreadLocalMap threadLocals = null;默认为空。 ThreadLocale中的get()方法:
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue();}ThreadLocalMap getMap(Thread t) { return t.threadLocals;}getMap()方法获取了当前线程的threadLocals变量,是一个ThreadLocalMap对象,默认为空。ThreadLocale.set()的时候,才会对threadLocales赋值。public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value);}
可以说,Thread的threadLocals是专门为ThreadLocal而存在的。每次调用TheadLocal.get()的时候,其实是以ThreadLocal对象为key,每个使用到同一个ThreadLocal的线程拥有相同的ThreadLocal引用,但因为每个thread维护自己的threadLocals对象,所以,取到的数据是不同的,是线程私有的。 以前理解的,是通过当前thread为key,取对应的值的想法是错误的。 为什么这么设计呢?个人理解,如果使用一个map来存储thread和value的键值对。一个应用程序得有无穷尽个线程,而map的值又不会因为线程的销毁而销毁,很快就会因为thread过多,而又无法释放资源而耗尽内存。每个线程维护一个ThreadLocalMap<ThreadLocal,T>对象,每次线程销毁的时候,值跟着就销毁了,不会存在内存耗尽的情况。 再深入的想想,并不一定非得在每个Thread对象中拥有一个threadLocals变量。如果ThreadLocal中有个容器,使用WeakReference<Thread>来保存thread和value的键值对,并不定时的清空weakreference.get()==null的键值对。应该也能实现同样的同能。但是复杂了很多。 下面说说ThreadLocal对WeakReference的使用。 Thread的threadLocals变量是一个ThreadLocalMap对象,是ThreadLocal的内部类。ThreadLocalMap不是一个map对象,只是取名为map而已。通过table保存Entity对象,从而维护值。 static class Entry extends WeakReference<ThreadLocal> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } } private Entry[] table; Entity继承WeakReference<ThreadLocal>,并且弱引用了key,即ThreadLocal对象。意味着,如果没有外部变量引用ThreadLocal对象,那么entity对象中的key将为null,value值不会被虚拟机销毁。这就是以下代码存在的原因:
private Entry getEntry(ThreadLocal key) { int i = key.threadLocalHashCode & (table.length - 1); Entry e = table[i]; if (e != null && e.get() == key) return e; else return getEntryAfterMiss(key, i, e);}private Entry getEntryAfterMiss(ThreadLocal key, int i, Entry e) { Entry[] tab = table; int len = tab.length; while (e != null) { ThreadLocal k = e.get(); if (k == key) return e; if (k == null) expungeStaleEntry(i); else i = nextIndex(i, len); e = tab[i]; } return null;}
以前我以为,只要是被WeakReference引用的对象,在下一次gc()的时候就会被回收掉,这是不对的。还少了一个条件,就是WeakReference引用的对象不再被其他外部对象引用的时候,那么,WeakReference引用的对象在下一次gc()的时候就会被回收掉。 看看这段代码,ThreadLocal的经典实用方式,但这里面有一些以前没考虑到的地方。
private static final ThreadLocal threadSession = new ThreadLocal(); public static Session getSession() throws InfrastructureException { Session s = (Session) threadSession.get(); try { if (s == null) { s = getSessionFactory().openSession(); threadSession.set(s); } } catch (HibernateException ex) { throw new InfrastructureException(ex); } return s;} }
threadSession是一个类的静态成员变量,就是说threadSession在程序运行过程中,不会存在不被引用的情况,所以即使threadSession被WeakReference引用,但绝对不会被gc()销毁。因此不用考虑ThreadLocalMap的Entity的key==null的情况。 为什么ThreadLocalMap不是map? 个人理解,如果ThreadLocalMap是map,那么怎么让虚拟机销毁不再使用资源?虽然可以通过其他的技术手段来销毁,但毕竟增加了工作量,而jdk提供这么好用的WeakReference,为什么不使用呢?而且ThreadLocalMap是一个内部类,很明显,就是为了ThreadLocel而设计的。
0 0
- ThreadLocale理解和对WeakReference的运用
- 对WeakReference的理解
- 论对DIV和Table运用的理解
- Java中关于WeakReference和WeakHashMap的理解
- 对StrongReference,WeakReference,SoftReference和PhantomReference的认识
- WeakReference的理解与使用
- WeakReference的理解与使用
- 关于对unity中协程运用的理解
- 对信号量Semaphore的理解与运用
- 对层和的运用
- 深入理解StrongReference,SoftReference, WeakReference和PhantomReference
- 对Java中线程安全Synchronized的深入理解和运用
- Java的WeakReference和SoftReference
- jdbc的事物管理与ThreadLocale
- Java WeakReference的理解与使用
- Java WeakReference的理解与使用
- Java WeakReference的理解与使用
- Java WeakReference的理解与使用
- Java设计模式——静态代理设计模式
- OpenMP编程入门之一
- hdu2057 A + B Again
- Oracle跨数据库操作
- Android并发编程之图文解析volatile关键字
- ThreadLocale理解和对WeakReference的运用
- Ubuntu14.04 JAVA环境配置
- 深度学习:推动NLP领域发展的新引擎
- OpenMP编程指南
- CenOS6.6下编译安装LAMP
- Chromium网页URL加载过程分析
- python subprocess 学习记录
- 视频上叠加汉字点阵文字
- easyui 在tabs子页面关闭当前tabs