[JAVA学习笔记-96]ThreadLocal
2017-06-10 12:39
531 查看
综述:
ThreadLocal可以理解为一个对象容器,这个容器为每个访问该容器的线程,封装了一个只对当前线程可见的对象。
也就是说,当多个线程共用一段代码时(例如同一个runnable对象分配给多个线程运行),ThreadLocal封装的对象
将会是线程安全的,只是访问的时候,需要用到set、get、remove、initValue等方法,否则,这些对象将会是多线程共享的,
是非线程安全的。
实现方法:
在Thread类中实现了一个 threadLocalMap<ThreadLocal key,T value>,执行ThreadLocal.set(T value)时,实质是获得当前Thread的这个 threadLocalMap ,将ThreadLocal对象作为Key(实质
是将该对象的HashCode作为Key)计算出下标(threadLocalMap是一个Entry[]),将指定的值存入数组中下标对应的位置。
在执行 ThreadLocal.get 时,再次获取当前Thread的 threadLocalMap,通过 ThreadLocal 对象作为key索引到保存的value,并返回。
【1、ThreadLocal 的 set方法:】
【2、ThreadLocal 的 getMap方法:】
【3、ThreadLocal 的 createMap 方法:】
【4、ThreadLocal.ThreadLocalMap 的构造方法:】
应用场景:
1、 web request handler
例如httpserver的hanler,向server注册一个GEThandler,每条http的GET请求都会调用此handler(假设只有一个handler对象,one thread per request),当并发的时候,handler中的
某些field会被多线程共享,且他们的值需要相互隔离(线程间不关心各自对这些field的修改),此时如果要线程安全,需要用ThreadLocal包装这些field。
2、 Reactor模式下的Accepter
多个连接并发的时候,Accepter可能需要用ThreadLocal隔离一些field,如果只有一个Accepter对象,而不是 new Thread(new Handler()).start(),那么可能需要用到ThreadLocal。
实例:
总结:
1、ThreadLocals are even more expensive than globals but they are certainly much better scoped.
2、ThreadLocal is for storing per-thread state past the execution scope of a method.
3、Another option is using synchronized to manage access to a shared member variable.
4、ThreadLocal,个人理解的应用场景为,当某个field为多线程共用,而field的值仅对各自线程有意义时,才用ThreadLocal包装隔离。
如果这个共用的field的值,对所有的线程都有意义,例如A线程修改了它,而B线程需要用到这个修改后的值,那么需要用 synchronized 或者用Atomicxxx族的对象来进行同步;
如果A线程修改的值,B线程并不关心,B线程只是与A线程共享了一段code而已,那么ThreadLocal可以用上。
通常情况下,尽量使用local variables在性能上更好。
ThreadLocal可以理解为一个对象容器,这个容器为每个访问该容器的线程,封装了一个只对当前线程可见的对象。
也就是说,当多个线程共用一段代码时(例如同一个runnable对象分配给多个线程运行),ThreadLocal封装的对象
将会是线程安全的,只是访问的时候,需要用到set、get、remove、initValue等方法,否则,这些对象将会是多线程共享的,
是非线程安全的。
实现方法:
在Thread类中实现了一个 threadLocalMap<ThreadLocal key,T value>,执行ThreadLocal.set(T value)时,实质是获得当前Thread的这个 threadLocalMap ,将ThreadLocal对象作为Key(实质
是将该对象的HashCode作为Key)计算出下标(threadLocalMap是一个Entry[]),将指定的值存入数组中下标对应的位置。
在执行 ThreadLocal.get 时,再次获取当前Thread的 threadLocalMap,通过 ThreadLocal 对象作为key索引到保存的value,并返回。
【1、ThreadLocal 的 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); /*如果当前线程没有创建这个map,则创建一个。*/ }
【2、ThreadLocal 的 getMap方法:】
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
【3、ThreadLocal 的 createMap 方法:】
void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
【4、ThreadLocal.ThreadLocalMap 的构造方法:】
ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); /*使用hashcode计算得到下标*/ table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); } private Entry[] table; static class Entry extends WeakReference<ThreadLocal> { /*注意这里的 WeakReference*/ /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) { /*构造函数*/ super(k); value = v; } }
应用场景:
1、 web request handler
例如httpserver的hanler,向server注册一个GEThandler,每条http的GET请求都会调用此handler(假设只有一个handler对象,one thread per request),当并发的时候,handler中的
某些field会被多线程共享,且他们的值需要相互隔离(线程间不关心各自对这些field的修改),此时如果要线程安全,需要用ThreadLocal包装这些field。
2、 Reactor模式下的Accepter
多个连接并发的时候,Accepter可能需要用ThreadLocal隔离一些field,如果只有一个Accepter对象,而不是 new Thread(new Handler()).start(),那么可能需要用到ThreadLocal。
实例:
public class Task implements Runnable{ private static AtomicInteger num = new AtomicInteger(0); private ThreadLocal<Integer> id = new ThreadLocal<Integer>(); @Override public void run() { // TODO Auto-generated method stub id.set(num.incrementAndGet()); /*每个线程从AtomicInteger返回一个唯一的值*/ System.out.println("id="+id.get()); /*每个线程的id值都是唯一的,并且相互之间感知不到,也不需要同步,因为此value实际上是Thread的local variable*/ } }
总结:
1、ThreadLocals are even more expensive than globals but they are certainly much better scoped.
2、ThreadLocal is for storing per-thread state past the execution scope of a method.
3、Another option is using synchronized to manage access to a shared member variable.
4、ThreadLocal,个人理解的应用场景为,当某个field为多线程共用,而field的值仅对各自线程有意义时,才用ThreadLocal包装隔离。
如果这个共用的field的值,对所有的线程都有意义,例如A线程修改了它,而B线程需要用到这个修改后的值,那么需要用 synchronized 或者用Atomicxxx族的对象来进行同步;
如果A线程修改的值,B线程并不关心,B线程只是与A线程共享了一段code而已,那么ThreadLocal可以用上。
通常情况下,尽量使用local variables在性能上更好。
相关文章推荐
- 【Java并发编程的艺术】【学习笔记】ThreadLocal与Fork/Join
- JAVA学习笔记(四十三)- ThreadLocal
- Java学习笔记(73)-----------ThreadLocal
- Android(java)学习笔记96:如何改变spinner系统自带的字体和颜色
- Java中的ThreadLocal的使用--学习笔记
- 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal
- Java并发28:ThreadLocal学习笔记-简介、基本方法及应用场景
- Java 学习笔记16:用ThreadLocal解决多线程安全问题
- Java多线程学习笔记2——ThreadLocal
- Java学习笔记--ThreadLocal
- JAVA学习笔记14——多态+内存分析
- 15. JAVA 反射机制 Part 2(动态代理、类的生命周期、工厂设计模式) ----- 学习笔记
- Java nio 学习笔记(四)
- Java学习笔记5 —— 变量
- java学习笔记(四)
- memcached高速缓存学习笔记003---利用JAVA程序操作memcached crud操作
- Java学习笔记(一)——类成员变量默认值
- 学习笔记_JavaSE_03_Java基础语法02
- JAVA新手学习笔记——Java实战经典(李兴华)第二部分D
- Java学习笔记----打印基本数据类型范围