本文由《精通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对有状态类线程安全化的解决思路。
- 大小: 15 KB
分享到:
相关推荐
在Spring Boot应用中,动态连接多数据库是一种常见的需求,尤其在构建分布式系统或者需要支持多种数据源的场景下。Spring Boot以其简洁的配置和强大的自动配置能力,使得处理这种复杂性变得相对简单。本篇文章将深入...
3. 在Spring或Hibernate等ORM框架中存放Session:每个线程拥有自己的数据库Session实例,确保事务的独立性。 例如,用ThreadLocal实现线程局部的Singleton模式,可以确保每个线程都有自己的Singleton实例,避免了...
在这个例子中,Spring MVC会查找请求体或查询参数中的`name`和`email`,并创建一个新的`User`对象,填充这些属性。此外,这个`User`对象还会自动添加到`ModelMap`中,以便在视图层中使用。 2. **作为方法**: 当`...
同时,对Spring BeanFactory和ApplicationContext的区别,Spring框架中使用到的设计模式,以及Spring Boot、Spring Cloud、Spring Security、Spring Data、Spring AMQP等其他Spring产品也要有所了解。 Netty作为高...
8. **反射机制**:理解Java反射的用途,包括在运行时动态创建对象、获取类信息、调用私有方法等,以及其在设计模式中的应用。 9. **JVM优化**:探讨JVM的运行参数设置,包括堆内存大小调整、垃圾回收策略选择、类...
* volatile和ThreadLocal的使用场景和原理 * synchronized和volatile的区别 * 模拟死锁场景和原子性与可见性 二、JVM相关 * JVM内存模型和GC机制 * GC的两种类型: Minor GC和Full GC * JVM里的classloader和双亲...
- IoC(Inversion of Control)和DI(Dependency Injection)的概念及其在Spring中的实现。 - AOP(Aspect-Oriented Programming)的理解与应用,如事务管理。 - Spring Boot快速开发的优势,以及Spring Cloud...
Java面试题集是针对Java开发者在面试过程中可能会遇到的各种问题的集合,涵盖了Java语言的核心概念、JVM原理、多线程、并发编程、设计模式、数据结构与算法、Spring框架、MyBatis、数据库相关知识等多个领域。...
11. **ThreadLocal 用途**:ThreadLocal 主要用于线程间的数据隔离,而不是数据共享。 12. **CAP 理论**:在分布式系统中,一致性、可用性和分区容错性无法同时满足,只能在三者之间做出权衡。 13. **final 方法与...
- Spring中的AOP(面向切面编程)及其主要用途。 - Spring的设计模式,如依赖注入、工厂模式等。 - Mybatis的动态SQL、$和#的区别,以及resultType和resultMap的使用场景。 7. **其他**: - 实际项目经验,能够...
文档可能讲解了Filter接口和Listener接口的实现,以及它们在实际应用中的用途,如权限控制、日志记录、性能监控等。 8. **三歪教你学HTTP.docx**:HTTP协议是Web应用的基础,涉及请求方法、状态码、头部信息等。这...
这份资料集涵盖了Java编程语言的核心概念、高级特性、框架应用以及实际开发中的常见问题,旨在帮助应聘者在面试中表现出扎实的技术功底。 1. **Java基础** - 类与对象:理解面向对象编程的基本原则,包括封装、...
面试者需要掌握线程创建的方式、线程同步机制(synchronized关键字、ReentrantLock等)、volatile关键字的作用以及ThreadLocal类的用途。 #### 二、高级特性与应用 1. **反射机制** - 反射是Java提供的一种能在...
14. **Spring Controller并发安全**:通过线程安全的设计原则,如避免在控制器中使用实例变量,使用`ThreadLocal`等方法确保控制器的线程安全。 #### 五、Netty框架 1. **BIO、NIO和AIO**:阻塞I/O(BIO)、非阻塞...
13. **MySQL的间隙锁**:在InnoDB引擎中,间隙锁防止在已存在的记录间隙插入新记录,确保事务隔离性。 14. **String、StringBuffer、StringBuilder**:String不可变,StringBuffer和StringBuilder可变,后者在单...
理解MVC模式,掌握Spring的依赖注入、AOP(面向切面编程)、事务管理,以及MyBatis和Hibernate的数据持久化技术,将有助于你在面试中脱颖而出。 八、数据库知识 熟悉SQL语言,包括查询、增删改查操作,以及索引、...
* 反射的用途及实现 * 自定义注解的场景及实现 * HTTP 请求的 GET 与 POST 方式的区别 * session 与 cookie 的区别 * JDBC 流程 * MVC 设计思想 * equals 与 == 的区别 * 集合 List 和 Set 的区别 * List 和 Map 的...