- 浏览: 92944 次
- 性别:
- 来自: 深圳
最新评论
-
liuguxing:
这个没研究过,用内嵌tomcat只是为了调试时不用发布到tom ...
Tomcat7内嵌服务器 -
helloqiner:
如何对嵌入式tomcat进行调优?如设置线程池数量,设置nio ...
Tomcat7内嵌服务器
Thread同步机制的比较
ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。
在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
由于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK 5.0通过泛型很好的解决了这个问题,在一定程度地简化ThreadLocal的使用,代码清单 9 2就使用了JDK 5.0新的ThreadLocal<T>版本。
概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
Spring使用ThreadLocal解决线程安全问题
我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态,因为有状态的Bean就可以在多线程中共享了。
一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程,如图9‑2所示:
图1同一线程贯通三层
这样你就可以根据需要,将一些非线程安全的变量以ThreadLocal存放,在同一次请求响应的调用线程中,所有关联的对象引用到的都是同一个变量。
下面的实例能够体现Spring对有状态Bean的改造思路:
代码清单3 TopicDao:非线程安全
由于①处的conn是成员变量,因为addTopic()方法是非线程安全的,必须在使用时创建一个新TopicDao实例(非singleton)。下面使用ThreadLocal对conn这个非线程安全的“状态”进行改造:
代码清单4 TopicDao:线程安全
不同的线程在使用TopicDao时,先判断connThreadLocal.get()是否是null,如果是null,则说明当前线程还没有对应的Connection对象,这时创建一个Connection对象并添加到本地线程变量中;如果不为null,则说明当前的线程已经拥有了Connection对象,直接使用就可以了。这样,就保证了不同的线程使用线程相关的Connection,而不会使用其它线程的Connection。因此,这个TopicDao就可以做到singleton共享了。
当然,这个例子本身很粗糙,将Connection的ThreadLocal直接放在DAO只能做到本DAO的多个方法共享Connection时不发生线程安全问题,但无法和其它DAO共用同一个Connection,要做到同一事务多DAO共享同一Connection,必须在一个共同的外部类使用ThreadLocal保存Connection。
小结
ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。
在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
由于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK 5.0通过泛型很好的解决了这个问题,在一定程度地简化ThreadLocal的使用,代码清单 9 2就使用了JDK 5.0新的ThreadLocal<T>版本。
概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
Spring使用ThreadLocal解决线程安全问题
我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态,因为有状态的Bean就可以在多线程中共享了。
一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程,如图9‑2所示:
图1同一线程贯通三层
这样你就可以根据需要,将一些非线程安全的变量以ThreadLocal存放,在同一次请求响应的调用线程中,所有关联的对象引用到的都是同一个变量。
下面的实例能够体现Spring对有状态Bean的改造思路:
代码清单3 TopicDao:非线程安全
public class TopicDao { private Connection conn;①一个非线程安全的变量 public void addTopic(){ Statement stat = conn.createStatement();②引用非线程安全变量 … } }
由于①处的conn是成员变量,因为addTopic()方法是非线程安全的,必须在使用时创建一个新TopicDao实例(非singleton)。下面使用ThreadLocal对conn这个非线程安全的“状态”进行改造:
代码清单4 TopicDao:线程安全
import java.sql.Connection; import java.sql.Statement; public class TopicDao { ①使用ThreadLocal保存Connection变量 private static ThreadLocal<Connection> connThreadLocal = new ThreadLocal<Connection>(); public static Connection getConnection(){ ②如果connThreadLocal没有本线程对应的Connection创建一个新的Connection, 并将其保存到线程本地变量中。 if (connThreadLocal.get() == null) { Connection conn = ConnectionManager.getConnection(); connThreadLocal.set(conn); return conn; }else{ return connThreadLocal.get();③直接返回线程本地变量 } } public void addTopic() { ④从ThreadLocal中获取线程对应的Connection Statement stat = getConnection().createStatement(); } }
不同的线程在使用TopicDao时,先判断connThreadLocal.get()是否是null,如果是null,则说明当前线程还没有对应的Connection对象,这时创建一个Connection对象并添加到本地线程变量中;如果不为null,则说明当前的线程已经拥有了Connection对象,直接使用就可以了。这样,就保证了不同的线程使用线程相关的Connection,而不会使用其它线程的Connection。因此,这个TopicDao就可以做到singleton共享了。
当然,这个例子本身很粗糙,将Connection的ThreadLocal直接放在DAO只能做到本DAO的多个方法共享Connection时不发生线程安全问题,但无法和其它DAO共用同一个Connection,要做到同一事务多DAO共享同一Connection,必须在一个共同的外部类使用ThreadLocal保存Connection。
小结
ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。
发表评论
-
如何实现返回?
2013-08-22 15:18 1656编写应用系统时,经常需要返回按钮,看原系统的实现多为重新跳转到 ... -
Tomcat7内嵌服务器
2013-08-21 11:53 1821import java.io.File; import ... -
String.getBytes()方法中的中文编码问题
2012-06-01 17:43 887String的getBytes()方法是得 ... -
java unicode utf-8 String.getBytes
2012-06-01 17:29 5035Unicode(统一码、万国码、单一码)是一种在计算机上使用的 ... -
eclipse模板之单例
2012-05-15 17:12 1984我们知道单例类的写法基本是一致的,每次写一个类都要写其单例实现 ... -
Too many open files
2012-05-15 14:45 1134java.net.SocketException: Too m ... -
支持中文的base64编码文件
2011-11-11 17:56 2157<!DOCTYPE html PUBLIC " ... -
slf4j和logback的使用
2011-09-23 14:18 4118项目中导入logback和slf4j的包,不需要log4j了, ... -
spring orm
2011-09-21 15:28 850public int add(T entity){ ... -
hbase单机安装
2011-08-29 22:03 2187下载hbase0.90.3 不要用root用户,以任意其他用户 ... -
设计自己的Annotation Java
2011-03-18 18:27 703Annotation在java的世界正 ... -
淘宝笔试题
2011-03-11 22:45 899给定一个整数,可以有三种操作:除2,加1和减1。怎样能在最少的 ... -
公钥和私钥
2011-02-25 11:15 1058公钥和私钥 ... -
Hibernate拦截SQL,动态改变表名
2011-01-20 10:11 7711转:http://www.iteye.com/topic/86 ... -
spring管理的hibernate事务不会自动flush的问题
2011-01-14 18:30 1697在spring中配置事务: 引用<bean id=&qu ... -
Java String对象的经典问题(new String())
2010-12-16 09:55 798转:http://sarin.iteye.com/bl ... -
深入浅出URL编码
2010-12-15 18:17 692深入浅出URL编码 转载出处:http://blog.csdn ... -
使用Servlet实现文件下载的时候,避免浏览器自动打开文件
2010-12-15 16:45 804response.addHeader("Conten ... -
丢掉tomcat,使用jetty开发
2010-08-12 15:50 1022package com.dymc.webservice; i ... -
JAVA线程
2009-10-06 19:16 847进程运行时都会被分配不同的内存空间,不同进程直接肯定不会有内存 ...
相关推荐
ThreadLocal应用示例及理解,这个写了相关的示例,可以参考一下。
javaee开发常见的模式有MVC模式,在C层中常常会再次分层,如:servlet(web层)、service(业务逻辑层)、dao(数据访问层),其中service和dao最容易混在一起,如转...所以,使用ThreadLocal可以解决这样的分层问题。
ThreadLocal
学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!
正确理解ThreadLocal.pdf
ThreadLocal的几种误区ThreadLocal的几种误区ThreadLocal的几种误区
主要介绍ThreadLocal的原理,实例分析以及注意事项
ThreadLocal保证一个类的实例变量在各个线程中都有一份单独的拷贝, 从而不会影响其他线程中的实例变量
JDBC事务的封装和Threadlocal实例,参考博客:http://blog.csdn.net/daijin888888/article/details/50988053
java 简单的ThreadLocal示例
本例以序列号生成的程序为例,展示ThreadLocal的使用
理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal
详解java底层实现原理,ThreadLocal底层实现的数据结构,为什么不会导致内存泄露
设计模式及ThreadLocal详细讲解资料,想要学习java或者提升自己技术的同学可以下载观看
ThreadLocal的基本原理,核心机制,源码,ThreadLocal在分布式架构中的应用,ThreadLocal在基础架构,开源中间件,使用非常广泛,建议掌握。
ThreadLocal源码(版本:Android4.3,,含注释)
ThreadLocal原理及在多层架构中的应用