- 浏览: 193951 次
- 性别:
- 来自: QD
文章分类
- 全部博客 (127)
- Struts2 (8)
- Web (27)
- 计算机基础 (2)
- 面试 (2)
- JQuery (4)
- MySQL (1)
- SQL (1)
- AJAX (3)
- Java (17)
- Javascript (36)
- 情感 (0)
- Oracle (7)
- Spring (5)
- FreeMarker (2)
- JSON (1)
- 表达式 (1)
- 线程 (4)
- WebService (10)
- MyEclipse (2)
- LDAP (1)
- Tomcat (1)
- NIO (1)
- Linux (1)
- ExtJS (4)
- Android (1)
- Dojo (2)
- Maven (9)
- Ant (7)
- 分布式 (1)
- Intellij IDEA (1)
最新评论
-
northc:
米饭军 写道如果文件已存在怎样避免应该会覆盖的
用Ant scp往远程linux传文件 -
米饭军:
如果文件已存在怎样避免
用Ant scp往远程linux传文件 -
luis025:
不支持列隐藏 硬伤
ExtJS4.0 分享Grid导出Excel插件(3.28更新支持4.1) -
rgbhje:
楼主大神,我把你的代码简单改了一小下,在4.2可以跑了
ExtJS4.0 分享Grid导出Excel插件(3.28更新支持4.1) -
rgbhje:
楼主大神,我把你的代码简单改了一小下,在4.2可以跑了
ExtJS4.0 分享Grid导出Excel插件(3.28更新支持4.1)
原文地址: http://www.iteye.com/topic/777716
ThreadLocal<T>类在Spring,Hibernate等框架中起到了很大的作用,对于其工作原理,很多网上的文章分析的不够彻底,甚至有些误解。
首先,为了解释ThreadLocal类的工作原理,必须同时介绍与其工作甚密的其他几个类(内部类)
1.ThreadLocalMap
2.Thread
可能有人会觉得Thread与ThreadLocal有什么关系,其实真正的奥秘就在Thread类中的一行:
- ThreadLocal.ThreadLocalMap threadLocals = null;
其中ThreadLocalMap的定义是在ThreadLocal类中,真正的引用却是在Thread类中
那么ThreadLocalMap究竟是什么呢?
可以看到这个类应该是一个Map,JDK的解释是
接下来的重点是ThreadLocalMap中用于存储数据的entry
- static class Entry extends WeakReference<ThreadLocal> {
- /** The value associated with this ThreadLocal. */
- Object value;
- Entry(ThreadLocal k, Object v) {
- super(k);
- value = v;
- }
- }
从中我们可以发现这个Map的key是ThreadLocal变量,value为用户的值,并不是网上大多数的列子key是线程的名字或者标识
到这里,我们就可以理解ThreadLocal究竟是如何工作的了
1.Thread类中有一个成员变量叫做ThreadLocalMap,它是一个Map,他的Key是ThreadLocal类
2.每个线程拥有自己的申明为ThreadLocal类型的变量,所以这个类的名字叫'ThreadLocal':线程自己的(变量)
3.此变量生命周期是由该线程决定的,开始于第一次初始(get或者set方法)
4.由ThreadLocal的工作原理决定了:每个线程独自拥有一个变量,并非共享或者拷贝
- /**
- * @author mxdba
- *
- */
- public class ThreadLocalSample {
- public static void main(String[] args) {
- ThreadTest test1 = new ThreadTest(10);
- ThreadTest test2 = new ThreadTest(20);
- test1.start();
- test2.start();
- }
- }
- /**
- * 此线程有两个ThreadLocal变量,但是由于ThreadLocal是延迟初始的,
- * 所以在debug时可以看到线程名为“线程20”的线程的ThreadLocalMap中没有thLcal2这个entry
- * @author mxdba
- *
- */
- class ThreadTest extends Thread {
- public static ThreadLocal<Integer> thLocal = new ThreadLocal<Integer>();
- public static ThreadLocal<String> thLocal2 = new ThreadLocal<String>();
- public Integer num;
- public ThreadTest(Integer num) {
- super("线程" + num);
- this.num = num;
- }
- @Override
- public void run() {
- Integer n = thLocal.get();
- if(num != 20) {
- String s = thLocal2.get();
- }
- if(n == null) {
- thLocal.set(num);
- }
- System.out.println(thLocal.get());
- }
- }
接下来分析一下源码,就更加清楚了
- /**
- * 关键方法,返回当前Thread的ThreadLocalMap
- * [[[每个Thread返回各自的ThreadLocalMap,所以各个线程中的ThreadLocal均为独立的]]]
- */
- ThreadLocalMap getMap(Thread t) {
- return t.threadLocals;
- }
- public T get() {
- Thread t = Thread.currentThread();
- /**
- * 得到当前线程的ThreadLocalMap
- */
- ThreadLocalMap map = getMap(t);
- if (map != null) {
- /**
- * 在此线程的ThreadLocalMap中查找key为当前ThreadLocal对象的entry
- */
- ThreadLocalMap.Entry e = map.getEntry(this);
- if (e != null)
- return (T)e.value;
- }
- return setInitialValue();
- }
- private T setInitialValue() {
- /**
- * 默认返回null,这个方法为protected可以继承
- */
- T value = initialValue();
- Thread t = Thread.currentThread();
- ThreadLocalMap map = getMap(t);
- if (map != null)
- map.set(this, value);
- else
- /**
- * 初次创建
- */
- createMap(t, value);
- return value;
- }
- /**
- * 给当前thread初始ThreadlocalMap
- */
- void createMap(Thread t, T firstValue) {
- t.threadLocals = new ThreadLocalMap(this, firstValue);
- }
通过上边的分析,我们发现,ThreadLocal类的使用虽然是用来解决多线程的问题的,但是还是有很明显的针对性
1.最明显的,ThreadLoacl变量的活动范围为某线程,并且我的理解是该线程“专有的,独自霸占”,对该变量的所有操作均有该线程完成!也就是说,ThreadLocal不是用来解决共享,竞争问题的。典型的应用莫过于Spring,Hibernate等框架中对于多线程的处理了
- private static final ThreadLocal threadSession = new ThreadLocal();
- public static Session getSession() throws InfrastructureException {
- Session s = (Session) threadSession.get();
- try {
- if (s == null) {
- s = getSessionFactory().openSession();
- threadSession.set(s);
- }
- } catch (HibernateException ex) {
- throw new InfrastructureException(ex);
- }
- return s;
- }
这段代码,每个线程有自己的ThreadLocalMap,每个ThreadLocalMap中根据需要初始加载threadSession,这样的好处就是介于singleton与prototype之间,应用singleton无法解决线程,应用prototype开销又太大,有了ThreadLocal之后就好了,对于需要线程“霸占”的变量用ThreadLocal,而该类实例的方法均可以共享。
2.关于内存泄漏:
虽然ThreadLocalMap已经使用了weakReference,但是还是建议能够显示的使用remove方法。
附上PDF 供大家研究.....
- ThreadLocal.pdf (189.6 KB)
- 下载次数: 5
发表评论
-
Java桌面程序打包成exe可执行文件(转)
2012-12-27 00:56 1216前言: 我们都知道Java可以将二进制程序打包成可执行 ... -
Java:应用Observer接口实践Observer模式(转)
2012-12-27 00:13 849转自:http://zhangjunhd.blog.51cto ... -
使用Java继承与泛型特性创建高效与安全的DAO对象
2012-06-27 17:15 0现在无论做什么应用,基本上都会有涉及对象持久化这方面的操 ... -
Java 批量插入数据(Oracle)
2012-03-28 16:21 2984//批量添加20000条数据用时8秒。 try { ... -
httpclient ,HtmlParser
2011-12-26 17:40 0有时间研究下吧... -
Java读取properties文件 【转】
2011-12-26 09:36 970不用可能会忘记.. 在这里转下别人的记录 方便以后 ... -
request 获取路径
2011-12-26 17:38 1129request.getRequestURI() /j ... -
ServletContext对象应用
2011-12-07 14:53 1326ServletContext对象是由谁创建的? 由Serv ... -
配置listener监听器(HttpSessionListener和HttpSessionBindingListener)细说
2011-12-07 14:52 1293from:http://blog.csdn.net/opnmz ... -
Servlet多线程
2011-12-02 17:47 1052关于Servlet多线程 其实Filter也 ... -
LDAP的特定错误集合
2011-11-28 11:29 2944LDAP的特定错误Error: com.macromedia. ... -
Filter多线程小细节
2011-11-26 14:50 1226在使用fileter的时候 如果在中间的位置需要fil ... -
JDBC调用Oracle的存储过程
2011-11-10 19:10 881本文主要是总结 如何实现 JDBC调用Oracle的存储过 ... -
ThreadLocal 与 synchronized
2011-11-06 17:31 709原帖:http://www.iteye.com/topic/1 ... -
关于 ThreadLocal
2011-11-06 17:26 1198ThreadLoca ... -
(转)Java编程中影响性能的一些特点
2011-11-04 11:42 651文中将提供一些在Java编程中影响性能的一些特点,为了能够 ... -
JSON与JAVA数据的转换
2011-10-21 12:24 923JSON-lib这个Java类包用于把bean,ma ... -
(转)Java内部类的用法
2011-10-21 09:05 767一、 定义 放在一个类的内部的类我们就叫内部类。 二、 作用 ... -
Java动态代理
2011-10-19 12:00 783代理模式 代理模式的 ... -
利用java的反射机制来访问类中的私有成员变量,私有构造方法,私有方法
2011-09-24 11:03 24221. 准备一个演示类 package my ...
相关推荐
`ThreadLocal<T>`提供了一个容器,用于存储类型为T的线程局部变量。创建`ThreadLocal<T>`实例时,会为每个线程分配一个独立的T类型的实例。这样,在多线程环境下,每个线程可以安全地使用自己的数据,而无需担心与...
private ThreadLocal<String> myThreadLocal = new ThreadLocal<>(); ``` 这里的`<String>`是可选的,用于指定ThreadLocal变量所存储的值的类型。如果不指定泛型,那么`get()`和`set()`方法将返回或接收Object类型...
ThreadLocal<String> threadLocal = new ThreadLocal<>(); ``` ### 设置和获取值 在ThreadLocal中,`set()`方法用于设置当前线程的ThreadLocal变量值,`get()`方法用于获取当前线程的ThreadLocal变量值。 ```java...
- 创建ThreadLocal实例:`ThreadLocal<T> threadLocal = new ThreadLocal<T>()` - 设置线程局部值:`threadLocal.set(value)` - 获取线程局部值:`T value = threadLocal.get()` - 移除线程局部值:`threadLocal...
private static final ThreadLocal<Session> sessionThread=new ThreadLocal<Session>(); private static final ThreadLocal<Transaction> transactionThread=new ThreadLocal<Transaction>(); private static ...
ThreadLocal<Integer> parentThreadLocal = new ThreadLocal<>(); ChildThread childThread = new ChildThread(parentThreadLocal); childThread.start(); ``` 2. **使用共享数据结构**: 父线程可以将ThreadLocal...
`ThreadLocal<T>`类在C# 5.0中引入,用于创建线程局部变量。这意味着每个线程都有自己的变量副本,互不影响。 例如: ```csharp ThreadLocal<int> threadCount = new ThreadLocal<int>(() => Environment....
ThreadLocal<String> threadLocal = new ThreadLocal<>(); ``` ##### T get() **用途**:返回当前线程所持有的 ThreadLocal 变量的副本。如果这是线程第一次访问,则会创建并初始化该副本。 **示例代码**: ```...
例如,可以使用`ThreadLocal<T>`结构体来定义一个线程局部变量,其中`T`是存储值的类型。 4. **线程生命周期管理**:ThreadlySwift会自动管理线程存储的生命周期。当线程结束时,与该线程相关的所有线程局部存储也...
总结来说,Activiti的工作流源码分析揭示了它在架构设计上的优秀之处,特别是在使用命令模式作为基础开发模型时,对职责分离和解耦所带来的益处。同时,Activiti基于Spring、ibatis等开源中间件的架构选择,为开发...
public static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDataSource(String dataSource) { CONTEXT_HOLDER.set(dataSource); } public static String get...
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); public static void setDataSource(String dataSourceName) { contextHolder.set(dataSourceName); } public static ...
public static ThreadLocal<Integer> thLocal = new ThreadLocal<>(); public static ThreadLocal<String> thLocal2 = new ThreadLocal<>(); public Integer num; public ThreadTest(Integer num) { this....
public static final ThreadLocal<Integer> PAGEINDEX = new ThreadLocal<>(); } ``` 然后,在需要设置或获取这些参数的地方,可以使用`PageParams.PAGESIZE.set()`和`PageParams.PAGEINDEX.set()`来设置值,通过`...
ThreadLocal<String> threadLocal = new ThreadLocal<>(); threadLocal.set("线程A的值"); // 在线程A中,可以获取到设置的值 System.out.println(threadLocal.get()); // 输出 "线程A的值" // 在线程B中,由于没有...
public static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDataSource(String dataSource) { CONTEXT_HOLDER.set(dataSource); } public static String get...
public static final ThreadLocal<String> THREAD_LOCAL = new ThreadLocal<>(); public static void setDataSource(String dataSource) { THREAD_LOCAL.set(dataSource); } public static String get...
java8 源码 设计模式 java 并发 public class Foo { // SimpleDateFormat ...ThreadLocal<SimpleDateFormat> ...ThreadLocal<SimpleDateFormat...ThreadLocal<Map>> MAPPING = ThreadLocal.withInitial(HashMap::new); public
ThreadLocal<T>简介和使用示例 ThreadLocal只有一个无参的构造方法public ThreadLocal(),它的相关方法包括: * public T get():获取当前线程的变量副本 * public void set(T value):设置当前线程的变量副本 * ...