TreadLocal用法

这里主要说两个方法,

1:set(T value)

2:get()

首先我们应该知道,每个线程Thread中都有一个对象ThreadLocal.ThreadLocalMap threadLocals = null;,这个可以从java源码中看到。

我们看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,如果为空则创建,

    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

 

        ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }

 注意这一行,table[i] = new Entry(firstKey, firstValue);它把ThreadLocal对象作为key,把线程引用作为value存入到ThreadLocalMap中。

 

然后我们看get()方法:

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }

 同样是得到当前线程引用,然后再得到当前线程的ThreadLocalMap,并从中找到以当前ThreadLocal为key的value,即上面set()方法中存入的值。

 

我们一般的用法是:

定义一个静态变量private final static ThreadLocal<Port> portCurrent = new ThreadLocal<>();

当线程启动时通过portCurrent.set(this)以portCurrent 为key把当前线程存入当前线程的ThreadLocalMap中,而在当前线程运行的其它地方通过portCurrent.get()方法,很容易就能得到当前线程的对象引用。

示例如下:

package myapp;
public class Test {
	public static void main(String[] args) {
		Thread t1 = new Thread(new T());
		Thread t2 = new Thread(new T());
		t1.start();
		t2.start();
		T t = T.local.get();
		if(t == null){
			System.out.println("t is null;");
		}
	}
}

class T implements Runnable{

	public static ThreadLocal<T> local = new ThreadLocal<T>();	
	public T(){
	}
	
	public void paint(){
		T t = local.get();
		System.out.println(t.toString());

	}
	
	@Override
	public void run() {
		local.set(this);
		while(true){
			paint();
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}	
}

 当线程运行时,首先通过local.set(this);把当前线程放入,而在paint()方法中,通过get()方法得到当前线程的引用,今儿对其进行操作。打印结果如下:
myapp.T@61de33
t is null;
myapp.T@ca0b6
myapp.T@61de33
myapp.T@ca0b6
myapp.T@61de33

之所以会打印"t is null“,是因为main()执行时函数同样是一个线程,当前线程的ThreadLocalMap中没有存放以local为key的value。只需在 T t = T.local.get();之前加一句 T.local.set(new T());即可,便不再有t is null的打印。

 

参考:http://www.iteye.com/topic/103804

 

你可能感兴趣的:(threadLocal)