内部类
因数threadlocalMap使用的是静态内部类,所以这里也介绍一下内部类
静态内部类和非静态内部类:
- 内部类:就是我是你的一部分,我了解你,我知道你的全部,没有你就没有我。(所以内部类对象是以外部类对象存在为前提的)
- 静态内部类:就是我跟你没关系,自己可以完全独立存在,但是我就借你的壳用一下,来隐藏自己。
- 内部类只有是静态的,其内部类中才能有静态属性和静态方法;
- 如果内部类非静态的,其内部类不能有静态属性和静态方法。
- 实例化一个非静态内部类:OutClass.InnerClass innerClass = new OutClass().new InnerClass();(依赖外部类的创建)
- 实例化一个静态内部类:OutClass,InnerClass innerClass = new OutClass.InnerClass();(不依赖外部类的创建)
静态内部类和非静态内部类在什么时候使用:
- 你设计类 B 的目的只是为了给类 A 使用,那么,我们就可将其设定为内部类,没有必要将类 B 设置成单独的 Java 文件,防止与其他类产生依赖关系。
ThreadLocal使用
ThreadLocal使用非常简单,它只对外提供了三个方法set(),get(),remove()
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);
}
- 获取当前线程,
- 根据当前线程获取ThreadLocalMap
- 将值放到TrheadLocalMap中
get():
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
- 获取当前线程,
- 根据当前线程获取ThreadLocalMap
- 从ThreadLocalMap中根据当前线程获取值,
remove():
private void remove(ThreadLocal<?> key) {
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)]) {
if (e.get() == key) {
e.clear();
expungeStaleEntry(i);
return;
}
}
}
- 根据线程获取值,然后清除
ThreadLocalMap
- 是ThreadLocal里的静态内部类,负责管理存储值,类似HashMap,
- ThreadLocalMap也是维护一个Entry数组,key值是指定的ThreadLocal做key值,
- ThreadLocalMap是存放在线程Thread对象中,每个线程会创建一个ThreadLocalMap
- ThreadLocalMap解决冲突的方式是非链表的方式,而是采用线性探测的方式,即在Entry数组中往后移
- 所以在创建多个ThreadLoacl后会增大冲突的概率