ThreadLocal理解

编程

  1. 使用ThreadLocal的时候我们保证了每个线程可以隔离使用对象,避免线程间的数据干扰。

常用例子:

public class ThreadLocalTest {

public static void main(String[] args) throws InterruptedException {

ThreadLocal tl=new ThreadLocal();

tl.set("123");

System.out.println(Thread.currentThread()+":"+tl.get());

Thread t=new Thread(

new Runnable() {

public void run() {

tl.set("456");

System.out.println(Thread.currentThread()+":"+tl.get());

}

});

t.start();

Thread.sleep(1000);

System.out.println(Thread.currentThread()+":"+tl.get());

}}

结果:

Thread[main,5,main]:123

Thread[Thread-0,5,main]:456

Thread[main,5,main]:123

从上面的例子可以看出来,每个线程保存的对象是隔离的!

  1. 代码分析

下面是Thread里面定义的对象,它的声明是在ThreadLocal里面的一个静态子类对象

ThreadLocal.ThreadLocalMap threadLocals = null;

这里是ThreadLocal的对象定义

static class ThreadLocalMap {

static class Entry extends WeakReference<ThreadLocal<?>> {

/** The value associated with this ThreadLocal. */

Object value;

//可以看出key为当前的ThreadLocal对象,value为保存的数据对象

Entry(ThreadLocal<?> k, Object v) {

super(k);

value = v;

}

}

}

下面set/get/getMap/createMap方法,可以存储数据

public void set(T value) {

//获取当前线程

Thread t = Thread.currentThread();

//根据当前的线程获取数据

ThreadLocalMap map = getMap(t);

if (map != null)

map.set(this, value);

else

createMap(t, value);

}

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 getMap(Thread t) {

return t.threadLocals;

}

void createMap(Thread t, T firstValue) {

t.threadLocals = new ThreadLocalMap(this, firstValue);

}

从上面可以看出写的代码示例,返回值是不同的因为线程是独立的,

独立线程会有自己的单独数据存储map,

至于ThreadLocal当作key是为了防止多个ThreadLocal在同一个线程当中做区分

  1. ThreadLocal做保存数据的key唯一性

//ThreadLocal类中有一个被final修饰的类型为int的threadLocalHashCode,它在该ThreadLocal被构造的时候就会生成,相当于一个ThreadLocal的ID

private final int threadLocalHashCode = nextHashCode();

//threadLocalHashCode值来源于这里

private static AtomicInteger nextHashCode =new AtomicInteger();

private static final int HASH_INCREMENT = 0x61c88647;

private static int nextHashCode() {

return nextHashCode.getAndAdd(HASH_INCREMENT);

}

以上是 ThreadLocal理解 的全部内容, 来源链接: utcz.com/z/515605.html

回到顶部