为ThreadLocal定制的ThreadLocalMap(一)

2014-11-24 03:19:40 · 作者: · 浏览: 0

静态内部类(Inner Class) 素数

为ThreadLocal定制的ThreadLocalMap 2010-10-04 16:00:17| 分类:JAVA线程安全| 标签:|字号大

小 订阅

ThreadLocalMap是java.lang.ThreadLocal的静态内部类。ThreadLocalMap表面看起来至少实现类似hashmap的功能,但是仔细分析它却有下面的属性。

首先,它只是尽量的让value保持在哈希值的位置或后面,

其次,它提供了对不同key(这里是ThreadLocal)对象的但hashCode相同的存储的支持。

最后,它对Key的引用是弱引用。这个和WeakHashMap一致。但这个和hashMap有点不一样,hashMap要使用用弱引用的话,

一般是对value进行弱引用的,而不是key.

也许有一天我们在自己的程序中需要类似ThreadLocalMap的功能。

以下是从ThreadLocalMap简化而来的代码:

其中Key对应JDK中的ThreadLocal

class Key {

final int hashCode = nextHashCode();

static AtomicInteger nextHashCode =

new AtomicInteger();

static final int HASH_INCREMENT = 0x61c88647;

static int nextHashCode() {

return nextHashCode.getAndAdd(HASH_INCREMENT);

}

}

class ThreadLocalMap {

static class Entry extends WeakReference {

Object value;

Entry(Key k, Object v) {

super(k);

value = v;

}

}

//初始值,必须是2的n次方

private static final int INITIAL_CAPACITY = 16;

/**

* The table, resized as necessary.

* table.length MUST always be a power of two.

*/

private Entry[] table;

private int size = 0;

/**

* The next size value at which to resize.

*/

private int threshold; // Default to 0

/**

* Set the resize threshold to maintain at worst a 2/3 load factor.

*/

private void setThreshold(int len) {

threshold = len * 2 / 3;

}

private static int nextIndex(int i, int len) {

return ((i + 1 < len) i + 1 : 0);

}

private static int prevIndex(int i, int len) {

return ((i - 1 >= 0) i - 1 : len - 1);

}

/**

* Construct a new map initially containing (firstKey, firstValue).

* ThreadLocalMaps are constructed lazily, so we only create

* one when we have at least one entry to put in it.

*/

ThreadLocalMap(Key firstKey, Object firstValue) {

table = new Entry[INITIAL_CAPACITY];

int i = firstKey.hashCode & (INITIAL_CAPACITY - 1);

table = new Entry(firstKey, firstValue);

size = 1;

setThreshold(INITIAL_CAPACITY);

}

private Entry getEntry(Key key) {

int i = key.hashCode & (table.length - 1);

Entry e = table[i];

if (e != null && e.get() == key)

return e;

else

return getEntryAfterMiss(key, i, e);

}

private Entry getEntryAfterMiss(Key key, int i, Entry e) {

Entry[] tab = table[i];

int len = tab.length;

while (e != null) {

Key k = e.get();

if (k == key)

return e;

if (k == null)

expungeStaleEntry(i);

else

i = nextIndex(i, len);

e = tab[i];

}

return null;

}

private void set(Key key, Object value) {

Entry[] tab = table;

int len = tab.length;

int i = key.hashCode & (len-1);

for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) {

Key k = e.get();

if (k == key) {

e.value = value;