在Java的多线程编程中,为保证多个线程对共享变量的安全访问,通常会使用synchronized来保证同一时刻只有一个线程对共享变量进行操作。 但在有些情况下,synchronized不能保证多线程对共享变量的正确读写。例如类有一个类变量,该类变量会被多个类方法读写,当多线程操作该类的实例对象时,如果线程对类变量有读取、写入操作就会发生类变量读写错误,即便是在类方法前加上synchronized也无效,因为同一个线程在两次调用方法之间时锁是被释放的,这时其它线程可以访问对象的类方法,读取或修改类变量。 这种情况下可以将类变量放到ThreadLocal类型的对象中,使变量在每个线程中都有独立拷贝,不会出现一个线程读取变量时而被另一个线程修改的现象。
下面举例说明:
public class QuerySvc {
private String sql;
private static ThreadLocal<string></string> sqlHolder = new ThreadLocal<string></string>();
public QuerySvc() {
}
public void execute() {
System.out.println("Thread " + Thread.currentThread().getId() +" Sql is " + sql);
System.out.println("Thread " + Thread.currentThread().getId() +" Thread Local variable Sql is " + sqlHolder.get());
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
sqlHolder.set(sql);
}
}
为了说明多线程访问对于类变量和ThreadLocal变量的影响,QuerySvc中分别设置了类变量sql和ThreadLocal变量,使用时先创建QuerySvc的一个实例对象,然后产生多个线程,分别设置不同的sql实例对象,然后再调用execute方法,读取sql的值,看是否是set方法中写入的值。 这种场景类似web应用中多个请求线程携带不同查询条件对一个servlet实例的访问,然后servlet调用业务对象,并传入不同查询条件,最后要保证每个请求得到的结果是对应的查询条件的结果。
使用QuerySvc的工作线程如下:
public class Work extends Thread {
private QuerySvc querySvc;
private String sql;
public Work(QuerySvc querySvc,String sql) {
this.querySvc = querySvc;
this.sql = sql;
}
public void run() {
querySvc.setSql(sql);
querySvc.execute();
}
}
运行线程代码如下:
QuerySvc qs = new QuerySvc();
for (int k=0; k<10; k++){
String sql = "Select * from table where id =" + k;
new Work(qs,sql).start();
}
先创建一个QuerySvc实例对象,然后创建若干线程来调用QuerySvc的set和execute方法,每个线程传入的sql都不一样,从运行结果可以看出sql变量中值不能保证在execute中值和set设置的值一样,在 web应用中就表现为一个用户查询的结果不是自己的查询条件返回的结果,而是另一个用户查询条件的结果;而ThreadLocal中的值总是和set中设置的值一样,这样通过使用ThreadLocal获得了线程安全性。
如果一个对象要被多个线程访问,而该对象存在类变量被不同类方法读写,为获得线程安全,可以用ThreadLocal来替代类变量。
分享到:
- 2007-07-11 14:13
- 浏览 3265
- 评论(1)
- 论坛回复 / 浏览 (1 / 3811)
- 查看更多
相关推荐
**线程局部变量(ThreadLocal)是Java编程中一个非常重要的工具类,它在多线程环境下提供了线程安全的数据存储。...在Java并发编程中,ThreadLocal是一个不可或缺的工具,尤其在需要线程私有数据的场景下。
Java源码解析ThreadLocal及使用场景 ThreadLocal是Java中一个非常重要的类,它在多线程环境下经常使用,用于提供线程本地变量。这些变量使每个线程都有自己的一份拷贝,使得多个线程可以独立地使用变量,不会彼此...
下面我们将深入探讨`ThreadLocal`的工作原理、使用场景以及常见误区。 `ThreadLocal`类的主要方法有以下几个: 1. `void set(T value)`:设置当前线程的线程局部变量的值。 2. `T get()`:返回当前线程的线程局部...
ThreadLocal的一个经典应用场景是在数据库连接池中,每个线程都可以有自己的数据库连接,而无需在多个线程间共享,这样可以简化代码并提高性能。另外,它也可以用于HTTP请求上下文,存储请求相关的数据,如用户会话...
4. **减少锁的使用**: 当多个线程需要共享同一资源,但每个线程只需要读取自己相关的数据时,`ThreadLocal`可以避免锁的使用,提升效率。 **注意事项** - 使用`ThreadLocal`后,应确保及时清理不再使用的变量,...
因为ThreadLocal使得原本可以独立运行的类变得依赖于线程环境,这限制了它们在没有ThreadLocal场景下的应用。因此,ThreadLocal应当谨慎使用,仅在确实需要线程隔离且其他同步手段无法满足需求时才考虑。 ...
总结,ThreadLocal是Java中处理线程局部数据的利器,特别适用于需要线程隔离的场景,如Web应用中的session管理。通过合理使用ThreadLocal,可以提升程序的并发性能并保证数据安全性。但同时,需要注意内存管理和避免...
**标题:“JDK的ThreadLocal理解(一)使用和测试”** **正文:** ThreadLocal是Java中的一个非常重要的线程安全工具类,它在多线程编程中扮演着独特的角色。通过创建ThreadLocal实例,我们可以为每个线程提供一个...
ThreadLocal的原理是什么,使用场景有哪些.md
尽管ThreadLocal在很多场景下都非常有用,但它也有一些潜在的问题需要注意,比如内存泄漏和过度使用可能导致系统资源浪费。因此,理解ThreadLocal的工作原理并谨慎使用是非常重要的。 在提供的"ThreadLocal示例...
计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料 计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料 计算机技术、IT咨询、人工智能AI理论介绍,学习参考资料 计算机技术、IT咨询、人工智能AI理论介绍,...
ThreadLocal的使用场景 在Java多线程编程中,变量的线程安全是一个非常重要的问题。特别是在使用共享变量时,如果没有正确地使用同步机制,可能会导致线程安全问题。ThreadLocal正是为了解决这个问题而生的。通过...
在具体实践中,开发者需要根据业务场景合理选择事务管理方式和ThreadLocal的使用,以保证系统的性能和数据一致性。例如,在分布式服务中,可能会使用分布式事务解决方案如两阶段提交(2PC)、补偿事务(TCC)等,而...
1.1、概述 1.2、原理 1.3、值得注意 2.1 ThreadLocal使用场景 2.2、深入源码查看实现原理
### 正确理解ThreadLocal:深入解析其工作原理与应用场景 #### 一、ThreadLocal的基本概念 `ThreadLocal`是Java平台提供的一种线程局部变量的解决方案,它为每一个使用该变量的线程都提供了独立的变量副本,使得每...
- **弱引用**:ThreadLocalMap的键使用的是弱引用,当ThreadLocal变量不再被引用时,垃圾收集器可以回收ThreadLocal对象,但其在ThreadLocalMap中的引用不会立即被移除,以防止导致内存泄漏。 - **线程生命周期**:...
javaee开发常见的模式有MVC模式,在C层中常常会再次分层,如:servlet(web层)、service(业务逻辑层)、dao(数据访问层),其中service和dao最容易混在一起,如转...所以,使用ThreadLocal可以解决这样的分层问题。
ThreadLocal 的原理、源码深度分析及使用 ThreadLocal 是 Java 语言中的一种机制,用于实现线程本地存储,能够帮助开发者在多线程环境下解决变量访问安全的问题。下面将对 ThreadLocal 的原理、实现机制、使用方法...
24. ThreadLocal使用场景:ThreadLocal为每个使用该变量的线程提供了一个独立的副本,使得线程间的变量互不干扰。 25. JVM命令:JVM提供了多种命令行工具,如jps、jstack、jmap等,用于监控和分析Java应用程序。 ...