- 浏览: 119731 次
- 性别:
- 来自: 湖南
文章分类
最新评论
-
一步一个天涯:
good.
tomcat配置热启动,我试过有用的方式 -
yuechen323:
哥们!!看了你博客的大部分文章,写的都非常的通俗易懂,谢谢~ ...
我在java中碰到的设计模式 -
悲剧了:
...
jstl
92. 现在来看怎么把三个方法保证同步,servlet是单实例多线程运行的,你去调用FlowCardServlet就
会启动一个线程,在这个线程里其实就调用了你写的那三个方法,现在我就只要保证你这三个方法都在一个线程里面就可以了。
93. 在同一个线程里保证使用一个connection这就涉及到一个类ThreadLocal
这个类不是本地线程的意思,这个类就在java.lang包中。作用:你放在这里面的东西,他会在整个线程里共享,在其它线程里不共享。
94. 不用框架要考虑的东西太多了,这样就会造成以后的维护成本提高啊。
95. 你可以这样理解,这个类的底层是 一个map{
key=当前线程变量001,也可以理解为这个是一个唯一标识的东西吧,不好理解,你就这么理解
value = new connection()
key=当前线程变量002
value = new connection() 这两个connection是不一样的,他们是不相互干扰的。
}
在这整个线程中就共享着一个
value对应的就是你具体的东西,你爱放什么就放什么,他接收一个Object参数。
96. ThreadLocal这个很重要,因为现在很多都使用这个东西。
这个类里面就四个方法。
public void set(T value){}你传一个connection进来,他就放到了一个map里面去了。
public void set(T value){
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if(map != null)
map.set(this,value);
else
createMap(t,value);
}别人再调用,他又map.set()设置一个了。如果有10个人设置进去东西了,我怎么就能拿到我的呢?
97. 他还有一个get(T value)方法。
map.get(0001);你当前线程对应的是0001 他就拿0001的东西。
98. 现在再建一个类来封装ThreadLocal
他命名命得好啊,connection的管理
public class ConnectionManager{
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();
现在都是在多线程中运行的,你开一个就开一个线程我得看看,在当前线程中绑没绑定一个connection
public static Connection getConnection(){
Connection conn = connectionHolder.get();
用了泛型你不用管了,里面就是coneciton
if(conn == null){ 当前线程没有绑定我就创建
JdbcInfo jdbcInfo = ConfigReader.getInstance().getJdbcInfo();
Class.forName(jdbcInfo.getDriverName());
conn = DriverManager.getConneciton(jdbcInfo.getUrl(),jdbcInfo.getUsername(),jdbcInfo.getPassword());
connectionHolder.set(conn);
}
}
return conn;
}
holder:持有
关闭方法,你想你要关闭,你怎么关,你只能关你自己的connection
public static void closeConnection(){
Connection conn = connectionHolder.get();
if(conn !=null){
conn.close();
conntionHolder.remove();你把他关了,他map里面的东西还存在啊,所以你得移除了。
}
}
99. 这思想就和我在方法中定义的变量只能在这个方法里面使用。
100. 我们还可以采用同步机制来解决线程安全问题
1. connection什么时候关闭,应该是那三个方法全部执行完
2. 这个connection应该是在FlowCardServiceImpl这一层开,在这一层关。
/**
* 采用ThreadLocal封装Connection
* ThreadLocal可以在同一个线程中共享变量
* @author Administrator
*
*/
public class ConnectionManager {
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();
/**
* 取得connection
* @return
*/
public static Connection getConnection() {
Connection conn = connectionHolder.get();
//如果在ThreadLocal中不存在与当前线程绑定的Connection
//那么我们就创建一个Connection,并将其放到ThreadLocal中
if (conn == null) {
try {
//取得jdbc配置信息
JdbcInfo jdbcInfo = ConfigReader.getInstance().getJdbcInfo();
Class.forName(jdbcInfo.getDriverName());
conn = DriverManager.getConnection(jdbcInfo.getUrl(), jdbcInfo.getUsername(), jdbcInfo.getPassword());
//放到ThreadLocal中
connectionHolder.set(conn);
} catch (ClassNotFoundException e) {
//记录日志可以将类不能找记录进去,这样可以更准确的定位问题
//但是给用户不应该抛出类不能找到,应该抛出用户能够理解的错误
e.printStackTrace();
throw new AppException("系统出现故障,请联系系统管理员!");
} catch (SQLException e) {
e.printStackTrace();
throw new AppException("系统出现故障,请联系系统管理员!");
}
}
return conn;
}
/**
* 关于connection
*/
public static void closeConnection() {
Connection conn = connectionHolder.get();
if (conn != null) {
try {
conn.close();
//从ThreadLocal中移除
connectionHolder.remove();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(PreparedStatement pstmt) {
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void commit(Connection conn) {
if (conn != null) {
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void rollback(Connection conn) {
if (conn != null) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void setAutoCommit(Connection conn, boolean autoCommit) {
if (conn != null) {
try {
conn.setAutoCommit(autoCommit);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Statement stmt) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
发表评论
-
读取配置的又一种读法
2010-08-29 11:05 806/** * 读取配置文件 * */ pub ... -
Thread.sleep(long)和object.wait(long)的共同点和不同点
2010-08-20 16:11 1537Thread.sleep(long)和object. ... -
取得context.xml中配置的连接池的Java代码的写法
2010-08-18 11:00 10437. bind(String name,Object obj ... -
uri与url的区别
2010-08-18 10:00 123323. 所以我们得把这个login.jsp这个页面除外。 ... -
java中的类加载器,与tomcat自己又做了一些类加载器的不同
2010-08-17 11:11 152452. 现在来讲一下java中的类加载器的原理(双亲委派机制 ... -
Cache-control缓存控制
2010-08-17 11:05 1190HTTP头的Expires与Cache-control ... -
map
2010-08-17 10:32 121379. map是一个非常强大的数据结构,他还可以用来表示一个 ... -
request.getSession(true)和request.getSession(false)的区别
2010-08-17 10:10 183677. 现在来看一下 request.getSession ... -
之前的一个表之间的关联我没能查出来
2010-08-17 10:07 77565. 现在要做这个分销 ... -
验证码:
2010-08-17 10:03 118558. 接下来看一下,验证码,现在很多网站都加上了验证码,其 ... -
Listener
2010-08-17 09:56 975107. 我们再介绍一个比 ... -
Jsp中的静态包含与动态包含:
2010-08-17 09:55 80899. 现在来讲静态和动态include 关于这个inc ... -
转发情况下的查询条件保持住:
2010-08-17 09:53 68296. 重点说一下上面的东西,${param.clientN ... -
一个servlet解决增删改查
2010-08-16 15:26 1763现在用三大框架来开发,快是很快,什么事务,转发的非常容易了,回 ... -
如果你的项目 数值类型要求非常严的话请用BigDecimal
2010-08-16 15:12 75558. 他说这个计算的事,如果你使用什么float,do ... -
不同服务器上开发程序时间同步的问题
2010-08-16 15:08 105049. 你现在在操作日期这个字段上放值,一般 是直接放一个n ... -
定位解决默认选中
2010-08-16 15:05 746jstl: <select name="ca ... -
jstl
2010-08-16 14:47 276498. 现在来看一下 el 表达式对运算符的支持: 1+ ... -
成员变量与类的属性的区别
2010-08-16 14:43 1231public class User{ pr ... -
java中synchronized浅析
2010-08-16 14:40 81069. 你也可以不在方法定义的时候声明synchroniz ...
相关推荐
**线程局部变量(ThreadLocal)是Java编程中一个非常重要的工具类,它在多线程环境下提供了线程安全的数据存储。ThreadLocal并不是一个变量,而是一个类,它为每个线程都创建了一个独立的变量副本,使得每个线程都...
ThreadLocal是Java编程语言中的一个类,用于在多线程环境中提供线程局部变量。它是一种特殊类型的变量,每个线程都有自己的副本,互不影响,从而实现线程间数据隔离。ThreadLocal通常被用来解决线程共享数据时可能...
例如,在Web应用服务器中,我们可以用ThreadLocal存储用户的会话信息,确保每个请求都访问到自己专属的数据。 ThreadLocal的使用通常包括以下步骤: 1. 创建ThreadLocal实例,声明变量类型。 2. 在需要的地方,通过...
理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal
在 `LeakingServlet` 的 `doGet` 方法中,如果 `ThreadLocal` 没有设置值,那么会创建一个新的 `MyCounter` 并设置到 `ThreadLocal` 中。关键在于,一旦 `MyCounter` 被设置到 `ThreadLocal`,那么它将与当前线程...
在需要的地方,你可以通过`set()`方法为当前线程的ThreadLocal副本设置值。 ```java threadLocal.set("这是线程A的值"); ``` 3. **获取线程局部变量的值:** 当你需要访问这个值时,使用`get()`方法。这将返回与...
ThreadLocal 整理 ThreadLocal 是 Java 中的一个重要组件,它能够在每个线程中保持独立的副本。这个功能是通过 Thread 类中的 threadLocals 属性来实现的,这个属性实际上是一个 Entry 数组,其中的每个 Entry 都...
可以在不同的线程中维护各自的事务状态,比如在Spring框架中,每个线程的ThreadLocal可以存储一个TransactionStatus对象,这样就可以在线程内部管理当前事务的状态,而不会影响到其他线程。这种方式在高并发的微服务...
ThreadLocal的使用方法通常是创建一个ThreadLocal实例,然后在需要的地方通过它的`set()`方法设置线程局部变量的值,通过`get()`方法获取该变量的副本。在生命周期结束后,通常需要调用`remove()`方法清除线程的副本...
**线程局部变量(ThreadLocal)** 在Java编程中,`ThreadLocal`是...以上就是关于`ThreadLocal`及其内部类`ThreadLocalMap`的基础知识,它们在多线程编程中起到关键作用,帮助开发者实现高效、安全的线程局部变量管理。
### 正确理解ThreadLocal:深入解析其工作原理与应用场景 #### 一、ThreadLocal的基本概念 `ThreadLocal`是Java平台提供的一种线程局部变量的解决方案,它为每一个使用该变量的线程都提供了独立的变量副本,使得每...
接着,将`ThreadLocal`对象作为键,对应的值作为值,存储到`ThreadLocalMap`中。 #### 四、ThreadLocal的内存泄漏问题及其解决方案 尽管使用弱引用来避免内存泄漏,但在某些情况下,仍然可能引起内存泄漏。例如,...
在服务器端,线程池的存在可能导致多个用户的请求被分配到同一个线程处理,因此,如果不注意清理,ThreadLocal变量可能会被不同用户访问到,造成数据泄露。 误区三:每个用户访问会有新的ThreadLocal 理论上来讲,...
4. **注意线程池中的ThreadLocal**:线程池中的线程可能会被重用,若不清理ThreadLocal,可能导致后续任务访问到错误的变量副本。 通过理解ThreadLocal的原理和最佳实践,我们可以更有效地利用它来解决多线程环境下...
学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!
本资料主要聚焦于两种设计模式以及Java中的ThreadLocal特性。 首先,我们来探讨单例模式。单例模式是一种确保一个类只有一个实例,并提供全局访问点的设计模式。在Java中,通常通过私有构造函数、静态工厂方法或...
3. **状态传递**:在 Quartz 作业的执行过程中,ThreadLocal 可以用来在不同阶段传递状态,比如在 Job 的 execute 方法中设置状态,然后在其他地方读取。 学习这个压缩包中的内容,可以帮助你理解如何在实际项目中...