本文由《精通Spring企业应用开发详解》一书第九章整理而成
一、ThreadLocal在Spring中的用途
我们知道 Spring通过各种数据模板降低了开发者使用各种数据持久技术的难度,这些模板类是线程安全的,也就是说,多个DAO可以复用一个模板实例而不会发生冲突。按照传统经验,如果某个对象是非线程安全的,在多线程安全环境下,对对象的访问必须采用synchronized进行线程同步。但是模板类并未采用线程同步机制,因为线程同步限制了并发访问,会带来很大的性能损失。此外,通过代码同步解决性能安全问题挑战很大,可能会增强好几倍的实现难度。那么模板类究竟仰仗何种魔法神功,可以在无须同步的情况下就化解纯种安全的难题呢?答案就是ThreadLocal!
ThreadLocal在Spring中发挥着重要的作用,在管理request作用域下的Bean、事务管理、任务高度、AOP等模块都出现了它们的身影,起着举足轻重的作用。
二、ThreaLocal是什么
ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地写出优美的多线程程序。
ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易了解一些。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自已的副本,而不会影响其他线程所对应的副本。从线程的角度看,目标变量就像是线程的本地变量,这也是类名中Local所要表达的意思。
三、ThreadLocal<T>的接口方法
void set(T value);//设置当前线程的线程局部变量的值
public Object get();//该方法返回当前线程所对应的线程局部变量
public void remove();//删除当前线程局部变量的值
protected Object initialValue();//返回当前线程局部变量的值
ThreadLocal怎样做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
四、一个ThreadLocal例子
运行结果:
五、Thread与同步机制的比较
ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题。
在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序缜密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象等繁杂的问题,程序设计和编写难度相对较大。
而ThreadLocal则从一个角度解决线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对变量进行同步了。
概括起来,对于多线程资源共享问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
五、Spring中使用ThreadLocal解决线程安全问题
一般的web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用属于一个线程,如下图:
这样用户就可以根据需要,将一些非线程安全的变量以ThreadLocal存放,在同一次请求响应的调用线程中,所有关联的对象引用到的都是同一个变量。下面是一个例子:
import java.sql.Connection;
import java.sql.Statement;
public class TopicDao{
private static ThreadLocal<Connection>connThreadLocal=new ThreadLocal<Connection>();
public static void main(String[] args){
if(connThreadLocal.get()==null{
Connection conn=ConnectionManager.getConnection();
connThreadLocal.set(conn);
return conn;
}else{
return connThreadLocal.get();
}
}
public void addTopic(){
Statement stat=getConnection.createStatement();
}
}
譔程序中保证了不同线程使用线程相关的Connection,而不会使用其他线程的Connection。因此,这个TopicDao就可以做到singleton共享了。
当然,这个例子很粗糙,但基本上说明了Spring对有状态类线程安全化的解决思路。
![点击查看原始大小图片](http://dl2.iteye.com/upload/attachment/0017/0949/af37ef80-0c6f-3c45-b91b-d36af5d6a13d-thumb.jpg)
- 大小: 15 KB
分享到:
相关推荐
NULL 博文链接:https://bijian1013.iteye.com/blog/2380233
NULL 博文链接:https://xxxxxfsadf.iteye.com/blog/518275
NULL 博文链接:https://yizhenn.iteye.com/blog/2293339
ThreadLocal的基本原理,核心机制,源码,ThreadLocal在分布式架构中的应用,ThreadLocal在基础架构,开源中间件,使用非常广泛,建议掌握。
ThreadLocal原理及在多层架构中的应用
详解java底层实现原理,ThreadLocal底层实现的数据结构,为什么不会导致内存泄露
ThreadLocal 在 Spring 中发挥着重要的作用,在管理 request 作用域的 Bean、事务管理、任务调度、AOP 等模块都出现了它们的身影,起着举足轻重的作用。要想了解 Spring 事务管理的底层技术,ThreadLocal 是必须...
ThreadLocal 中内存泄漏和数据丢失问题的问题浅析及解决方案 ThreadLocal 是 Java 中的一种线程本地存储机制,它可以解决线程之间的数据传递问题。然而,在使用 ThreadLocal 时,可能会出现内存泄漏和数据丢失问题...
ThreadLocal入门教程。 讲解了线程安全和ThreadLocal的使用的基本知识。
ThreadLocal
主要介绍了详解Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.1.1. @Configurable object的单元测试 6.8.1.2. 多application context情况下的处理 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来...
ThreadLocal应用示例及理解,这个写了相关的示例,可以参考一下。
Java中ThreadLocal的设计与使用.doc
6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7...
学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!
ThreadLocal的几种误区ThreadLocal的几种误区ThreadLocal的几种误区
例如,Spring Security 中的 ThreadLocalSecurityContextHolderStrategy 类就是使用 ThreadLocal 来实现的。 三、如何创建一个 ThreadLocal 实例 创建一个 ThreadLocal 实例非常简单,只需要使用 private static ...