最近学了学threadLocal
首先第一java中的引用类型 分为强软弱虚
强引用就是Object c =new Object() 强引用,不会被回收,只要有引用指向就不会被回收,即使报OOM也不会被回收
软引用
软引用
即对象的软引用。如果一个对象具有软引用,内存空间足够,垃 圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用做缓存。使用软引用能防止内存泄露,增强程序的健壮性 一般用于做缓存
SoftReference<byte[]>m=new SoftReference<>(new byte[10*1024*1024]);
弱引用 WeakReference<M> m=new WeakReference<M>(new M());
gc来一次清一次
虚引用不太了解 也没有听明白
我们想下如果我们有一个变量X 此时需要把这个x通过方法一层一层传过来,但是有些时候,某些类库是传不过来的,
@Transtanct如果这个方法想支持事务 他必须要拿到数据库连接connection
呢么这个connection怎么传过来,绝对不能说和之前的connection不一样
他把这个connection 放到threadLocal,
一定是说每一个线程调用这一套过程用的connection必须是同一个connection
testDemo
static ThreadLocal<Person> t1=new ThreadLocal<>();
{
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t1.get());
});
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.set(new Person());
});
}
t1.set(new Person());
当我们点击进去set的时候
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
// 拿到当前线程,也就是说 我们 t1.set(new Person());的时候实际上是把t1为key,new Person 作为value 存入的 一个map中
我们再来看这个map , t.threadLocals; 他这个map其实是调用了线程的 threadLocals
ThreadLocal.ThreadLocalMap threadLocals = null;
也就是说每一个线程都有自己独立的 threadLocals
也就是说 当我们 t1.set(new Person()); 的时候实际上是调用了当前线程的 threadLocals .set()//并且此时是以 tl[threadLocal对象为key],new Person() 为value 的
我们再来看看这个 tab[i] = new Entry(key, value);
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
他此时在构造这个Entry 的时候,将我们的t1 设置成为了虚引用
也就是说当我们调用了 t1.set(new Person()); 的时候
实际上是调用了当前线程的threadLocals.set(tl,new Person())// 把这个threadLocal对象作为Key,new Person作为value, 然后将threadLocal 作为一个弱引用
但是当此时是一个弱引用的时候 gC来一次清理一层,对于hashmap
当你的key 为null的话 你此时要把这个value或者说这一条数据给remove了,
假如这个线程是在线程池中 线程中的threadLocals没有被清理掉
清空threadLocals【map】