目前ThreadLocal使用场景最多的就是多数据源的切换了.我们在使用ThreadLocal在不同线程之间切换数据源的时候要其实有很多知识点需要注意cuiyaonan2000@163.com
线程的状态线程入门的知识,但是在后续的设计中会应用到cuiyaonan2000@163.com
系统线程的状态- 新建(NEW)
- 就绪(RUNNABLE)
- 运行(RUNNING)
- 阻塞(BLOCKING): sleep,wating,blocking
- 死亡(DEAD)
Java的线程状态跟系统的差不多,同时new Thread()对象可以通过getState()查看到JDK给你的线程提供的几种状态cuiyaonan2000@163.com
人工翻译一下(Java貌似就多了个超时状态):
- 新建: 一个线程尚未开始的时候是这个状态
- 可运行状态: 一个线程在JVM中运行是的状态(为什么不是Running)
- 阻塞: 一个线程阻塞等待一个监控锁的时候在此状态
- 等待状态
- 超时状态
- 终止状态
其实我要重温这个的目的是想确定,一个线程会不会在阻塞的时候执行其它的任务,如果是这样ThreadLocal就你妹的没用了cuiyaonan2000@163.com
ReferenceJava 提供了如下的抽象类
- java.lang.ref.Reference
- java.lang.ref.SoftReference
- java.lang.ref.WeakReference
- java.lang.ref.PhantomReference
强引用的对象是不可以GC回收的,不可以随意回收具有强引用的对象来解决内存不足的问题。------除非对象没有引用指向才会被GC回收.否则不在GC的范围内
把一个对象赋给一个引用类型变量,则为强引用。
在Java中,强引用是一种默认的状态,除非JVM虚拟机停止工作。
String email = "cuiyaonan2000@163.com";
软引用
软引用的意思是只有在内存不足的情况下,被引用的对象才会被回收。
可以通过java.lang.ref.SoftReference使用软应用.该类有2个构造行数
/**
* Creates a new soft reference that refers to the given object. The new
* reference is not registered with any queue.
*
* @param referent object the new soft reference will refer to
*/
public SoftReference(T referent) {
super(referent);
this.timestamp = clock;
}
/**
* Creates a new soft reference that refers to the given object and is
* registered with the given queue.
*
* @param referent object the new soft reference will refer to
* @param q the queue with which the reference is to be registered,
* or null if registration is not required
*
*/
public SoftReference(T referent, ReferenceQueue k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
}
再看下set方法,key就是ThreadLocal 由它的hashcode来计算出数组的下标,来存放最终的value.
这里ThreadLocal是我们代码声明的,是固定的,它所保存的值是存储在不同线程中的,相当于ThreadLocal是一把钥匙,用来从不同的线程中取出自己放置的值cuiyaonan2000@163.com
这样子就满足了不同线程的ThreadLocal钥匙会取出不同的值
private void set(ThreadLocal key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal k = e.get();
if (k == key) {
e.value = value;
return;
}
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
tab[i] = new Entry(key, value);
int sz = ++size;
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
ThreadLocal内存溢出的原因
因为ThreadLocalMap 是使用ThreadLocal作为Key ,同时ThreadLocalMap跟Thread的声明周期一样长(这是废话因为,ThreadLocalMap是Thread的一个属性cuiyaonan2000@163.com),所以ThreadLocalMap会一直保持对ThreadLocal的引用,根据java的可达分析原则,ThreadLocalMap中的value不会被清理, 当然当Thread关闭的时候可以被清理,但是我们现在都是用的线程池,所以会造成内存溢出.