浅析 ThreadLocal
2017-04-14 09:39
399 查看
一、ThreadLocal类说明
ThreadLocal,很容易让人望文生义,直译"本地线程"。ThreadLocal不是一个thread,是thread的局部变量。使用ThreadLocal维护变量时,它为每个使用它的线程提供独立的线程副本,每个线程可以改变自己的副本,而不会影响到其它线程对应的副本。
从线程的角度看,目标变量就象是线程的本地变量,这也是类名中"Local"所要表达的意思。
二、ThreadLocal常用方法
①、当前变量的初始值
protected T initialValue()
源码 如下,该方法是一个protected方法,显然是为了让子类覆盖而设计的。该方法是在get|set会调用,且只会被调一次。ThreadLocal缺省实现直接返回null
②、设置当前线程的线程局部变量值
void set(T value)
③、返回当前线程的线程局部变量值
public T get()
④、删除当前线程的线程局部变量值,节省内存的占用。
public void remove()
三、下面我们通过一个具体例子,看看ThreadLocal的具体用法---Id生成器
id生成器
线程
结果 :
从上述结果,每个线程只会更改自己的局部变量,并没有发生互相干扰的情况。可以看出来,ThreadLocal为使用它的线程提供独立的副本。
不信?我们下面再通过一个不使用ThreadLocal来验证下。
结果
仔细观察下结果,三个线程同时访问一个局部变量id,发生了互相干扰的情况。
四、拓展
看下ThreadLocal源码,底层是用Map实现的。我们可以自己设计一个ThreadLocal
ThreadLocal,很容易让人望文生义,直译"本地线程"。ThreadLocal不是一个thread,是thread的局部变量。使用ThreadLocal维护变量时,它为每个使用它的线程提供独立的线程副本,每个线程可以改变自己的副本,而不会影响到其它线程对应的副本。
从线程的角度看,目标变量就象是线程的本地变量,这也是类名中"Local"所要表达的意思。
二、ThreadLocal常用方法
①、当前变量的初始值
protected T initialValue()
源码 如下,该方法是一个protected方法,显然是为了让子类覆盖而设计的。该方法是在get|set会调用,且只会被调一次。ThreadLocal缺省实现直接返回null
protected T initialValue() { return null; }
②、设置当前线程的线程局部变量值
void set(T value)
③、返回当前线程的线程局部变量值
public T get()
④、删除当前线程的线程局部变量值,节省内存的占用。
public void remove()
三、下面我们通过一个具体例子,看看ThreadLocal的具体用法---Id生成器
id生成器
public interface Sequence { public int getId(); } public class LocalSequenceImpl implements Sequence { private ThreadLocal<Integer> container = new ThreadLocal<Integer>() { @Override protected Integer initialValue() { return 0; }; }; @Override public int getId() { container.set(container.get() + 1); return container.get(); } }
线程
public class ThreadLocalDemo extends Thread { private static Sequence obj; @SuppressWarnings("static-access") public ThreadLocalDemo(Sequence obj) { this.obj = obj; } public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + " : " + obj.getId()); } } public static void main(String[] args) { Sequence obj = new LocalSequenceImpl(); test(obj); } static void test(Sequence obj) { ThreadLocalDemo thread1 = new ThreadLocalDemo(obj); ThreadLocalDemo thread2 = new ThreadLocalDemo(obj); ThreadLocalDemo thread3 = new ThreadLocalDemo(obj); thread1.start(); thread2.start(); thread3.start(); } }
结果 :
Thread-0 : 4000 1 Thread-1 : 1 Thread-1 : 2 Thread-2 : 1 Thread-2 : 2 Thread-2 : 3 Thread-1 : 3 Thread-0 : 2 Thread-0 : 3
从上述结果,每个线程只会更改自己的局部变量,并没有发生互相干扰的情况。可以看出来,ThreadLocal为使用它的线程提供独立的副本。
不信?我们下面再通过一个不使用ThreadLocal来验证下。
public class SequenceImpl implements Sequence { private static int id = 0; @Override public int getId() { id = id + 1; return id; } }
结果
Thread-0 : 2 Thread-0 : 4 Thread-0 : 5 Thread-2 : 3 Thread-2 : 6 Thread-2 : 7 Thread-1 : 1 Thread-1 : 8 Thread-1 : 9
仔细观察下结果,三个线程同时访问一个局部变量id,发生了互相干扰的情况。
四、拓展
看下ThreadLocal源码,底层是用Map实现的。我们可以自己设计一个ThreadLocal
public class MyThreadLocal<T> {
private Map<Thread, T> container = Collections.synchronizedMap(new HashMap<>());
public void set(T value) {
container.put(Thread.currentThread(), value);
}
public T get() {
Thread currentThread = Thread.currentThread();
T value = container.get(Thread.currentThread());
if(value == null && !container.containsKey(currentThread)) {
value = initialValue();
container.put(Thread.currentThread(), value);
}
return value;
}
protected T initialValue() { return null; }
}
相关文章推荐
- ThreadLocal源码浅析
- Java ThreadLocal使用浅析
- ThreadLocal示例及源码浅析
- Java ThreadLocal类理解与浅析
- 源码浅析ThreadLocal类
- ThreadLocal在多线程中的作用和原理浅析(模拟学生入学报到场景)
- 浅析Java中通过ThreadLocal实现线程绑定来传递参数
- ThreadLocal的浅析
- 浅析 ThreadLocal
- JAVA ThreadLocal对象浅析
- 浅析ThreadLocal
- 浅析 ThreadLocal
- 【并发】ThreadLocal源码浅析
- 线程变量浅析ThreadLocal
- 小葵花妈妈课堂开课了:《ThreadLocal 浅析》
- 关于java多线程浅析四:ThreadLocal
- ThreadLocal浅析
- 浅析反射、工厂和配置文件
- 数据库中事务的浅析
- 浅析C++中的this指针