ThreadLocal模式

线程封闭#

当访问共享的可变数据时,通常需要同步.一种避免同步的方法就是不共享数据.如果仅在单线程内访问数据,就不需要同步.这种技术被称为线程封闭,它是实现线程安全性的最简单方式之一.当某个对象封闭在一个线程中,这种用法将自动实现线程安全性,即使被封闭的对象本身不是线程安全的.

ThreadLocal类##

  • jdk实现的ThreadLocal是典型的维持线程封闭性的方法,这个类能使线程中的某个值与保存的对象关联起来.ThreadLocal提供了set和get等访问接口和方法,这些方法为每个使用这个变量的线程都存有一份独立的副本.
  • ThreadLocal对象通常用于防止对可变的单实例变量或全局变量进行共享.

一个小例子来使用ThreadLocal类

public class Counter {
private static ThreadLocal<Integer> context = new ThreadLocal<Integer>() {
	protected  Integer initialValue() {
		return 10;
	}
};

public static Integer get() {
	return context.get();
}


public static void set(Integer value) {
	context.set(value);
}

public static Integer getNextCounter() {
	context.set(context.get()+1);
	return context.get();
}

}

创建多个线程访问ThreadLocal类初始化的变量.

public class ThreadLocalTest extends Thread{

public void run() {
	for (int i = 0; i < 3; i++) {
		System.out.println("Thread["+Thread.currentThread().getName()+"],counter="
				+Counter.getNextCounter());
	}
}


public static void main(String[] args) {
	ThreadLocalTest thread1 = new ThreadLocalTest();
	ThreadLocalTest thread2 = new ThreadLocalTest();
	ThreadLocalTest thread3 = new ThreadLocalTest();
	thread1.start();
	thread2.start();
	thread3.start();
}

}

3个线程对初始值的修改都互不影响

Thread[Thread-1],counter=11
Thread[Thread-1],counter=12
Thread[Thread-1],counter=13
Thread[Thread-2],counter=11
Thread[Thread-2],counter=12
Thread[Thread-2],counter=13
Thread[Thread-0],counter=11
Thread[Thread-0],counter=12
Thread[Thread-0],counter=13

get和set方法是如何与当前线程关联起来的?##

public class ThreadLocal<T> {

    public void set(T value) {
        Thread t = Thread.currentThread();//获取当前访问的线程
        ThreadLocalMap map = getMap(t);//获取当前线程中的ThreadLocalMap
        if (map != null)
            map.set(this, value);//如果不为空的话,就以当前hreadLocal实例为key,存储的对象为值存入ThreadLocalMap 中
        else
            createMap(t, value);//创建一个ThreadLocalMap 
    }

        void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);//同样以当前ThreadLocal实例为key
    }


    public T get() {
        Thread t = Thread.currentThread();//获取当前访问的线程
        ThreadLocalMap map = getMap(t);//获取当前线程中的ThreadLocalMap
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);//获取当前线程中以当前ThreadLocal实例为key的变量值
            if (e != null)
                return (T)e.value;
        }    
        return setInitialValue();//当map不存在的时候设置初始值.
    }

        ThreadLocalMap getMap(Thread t) {//从线程中获取对应的ThreadLocalMap,是多个ThreadLocal的集合.
        return t.threadLocals;
    }


}
原文地址:https://www.cnblogs.com/itsrobin/p/5180581.html