ThreadLocal

2019-01-23  本文已影响0人  modou1618

一 初始化

private final int threadLocalHashCode = nextHashCode();

private static AtomicInteger nextHashCode =
        new AtomicInteger();

private static final int HASH_INCREMENT = 0x61c88647;

private static int nextHashCode() {
    return nextHashCode.getAndAdd(HASH_INCREMENT);
}
private static ThreadLocal<Random> localRandom3 = new ThreadLocal<Random>();
public Random get() {
    Random random = localRandom3.get();
    if (random == null) {
        random = new Random();
        localRandom3.set(random);
    }

    return random;
}
private static ThreadLocal<Random> localRandom2 = new ThreadLocal<Random>(){
    @Override
    protected Random initialValue() {
        return new Random();
    }
};
private static ThreadLocal<Random> localRandom = ThreadLocal.withInitial(()->new Random());

public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
    return new ThreadLocal.SuppliedThreadLocal<>(supplier);
}

static final class SuppliedThreadLocal<T> extends ThreadLocal<T> {

    private final Supplier<? extends T> supplier;

    SuppliedThreadLocal(Supplier<? extends T> supplier) {
        this.supplier = Objects.requireNonNull(supplier);
    }

    @Override
    protected T initialValue() {
        return supplier.get();
    }
}

二 set()

Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);

ThreadLocal.ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

2.1 map不存在

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocal.ThreadLocalMap(this, firstValue);
}
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
    table = new ThreadLocal.ThreadLocalMap.Entry[INITIAL_CAPACITY];
    int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
    table[i] = new ThreadLocal.ThreadLocalMap.Entry(firstKey, firstValue);
    size = 1;
    setThreshold(INITIAL_CAPACITY);
}

2.2 map已存在

ThreadLocal<?> k = e.get();
if (k == key) {
    e.value = value;
    return;
}
if (k == null) {
    replaceStaleEntry(key, value, i);
    return;
}
private boolean cleanSomeSlots(int i, int n) {
    boolean removed = false;
    ThreadLocal.ThreadLocalMap.Entry[] tab = table;
    int len = tab.length;
    do {
        i = nextIndex(i, len);
        ThreadLocal.ThreadLocalMap.Entry e = tab[i];
        if (e != null && e.get() == null) {
            n = len;
            removed = true;
            i = expungeStaleEntry(i);
        }
    } while ( (n >>>= 1) != 0);
    return removed;
}

2.2.1 replaceStaleEntry

2.2.2 expungeStaleEntry(i)

tab[staleSlot].value = null;
tab[staleSlot] = null;
size--;
ThreadLocal<?> k = e.get();
if (k == null) {
    e.value = null;
    tab[i] = null;
    size--;
} 
int h = k.threadLocalHashCode & (len - 1);
if (h != i) {
    tab[i] = null;

    // Unlike Knuth 6.4 Algorithm R, we must scan until
    // null because multiple entries could have been stale.
    while (tab[h] != null)
        h = nextIndex(h, len);
    tab[h] = e;
}

三 get()

private T setInitialValue() {
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}

四 remove()

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
        m.remove(this);
}
private void remove(ThreadLocal<?> key) {
    ThreadLocal.ThreadLocalMap.Entry[] tab = table;
    int len = tab.length;
    int i = key.threadLocalHashCode & (len-1);
    for (ThreadLocal.ThreadLocalMap.Entry e = tab[i];
         e != null;
         e = tab[i = nextIndex(i, len)]) {
        if (e.get() == key) {
            e.clear();
            expungeStaleEntry(i);
            return;
        }
    }
}

五 ThreadLocalMap存储格式

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

弱引用对象的存在不会阻止它所指向的对象被垃圾回收器回收。弱引用最常见的用途是实现规范映射(canonicalizing mappings,比如哈希表)。
假设垃圾收集器在某个时间点决定一个对象是弱可达的(weakly reachable)(也就是说当前指向它的全都是弱引用),这时垃圾收集器会清除所有指向该对象的弱引用,然后把这个弱可达对象标记为可终结(finalizable)的,这样它随后就会被回收。与此同时或稍后,垃圾收集器会把那些刚清除的弱引用放入创建弱引用对象时所指定的引用队列(Reference Queue)中。

实际上,Java中存在四种引用,它们由强到弱依次是:强引用、软引用、弱引用、虚引用。下面我们简单介绍下除弱引用外的其他三种引用:
强引用(Strong Reference):通常我们通过new来创建一个新对象时返回的引用就是一个强引用,若一个对象通过一系列强引用可到达,它就是强可达的(strongly reachable),那么它就不被回收
软引用(Soft Reference):软引用和弱引用的区别在于,若一个对象是弱引用可达,无论当前内存是否充足它都会被回收,而软引用可达的对象在内存不充足时才会被回收,因此软引用要比弱引用“强”一些
虚引用(Phantom Reference):虚引用是Java中最弱的引用,那么它弱到什么程度呢?它是如此脆弱以至于我们通过虚引用甚至无法获取到被引用的对象,虚引用存在的唯一作用就是当它指向的对象被回收后,虚引用本身会被加入到引用队列中,用作记录它指向的对象已被回收。

上一篇下一篇

猜你喜欢

热点阅读