事务处理中的ThreadLocal的使用
2015-09-10 20:46
281 查看
事务处理中的ThreadLocal的使用
简单的理解ThreadLocal
所谓ThreadLocal,简单一点想,就是一个全局的Map,Map的key是线程对象,value是你要保存的对象进入某个线程后,就可以从map中取得之前存储的相应线程关联的对象。
NT:ThreadLocal并不是一个Map,但用Map来理解是没有问题的
在事务中使用ThreadLocal
确保所有的sql语句都在同一个开启了事务的链接上执行,这时候就可以使用ThreadLocal来解决这个问题。解决思路:
代码实现:
//绑定开启了链接的connection到ThreadLocal的JdbcUtils工具类 public class JdbcUtils { private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); //map public static void startTransaction(){ try{ //得到当前线程上绑定连接开启事务 Connection conn = tl.get(); if(conn==null){ //代表线程上没有绑定连接 conn = ds.getConnection(); //ds 代表数据源, 这里省略他的代码 tl.set(conn); } conn.setAutoCommit(false); }catch (Exception e) { throw new RuntimeException(e); } } public static void commitTransaction(){ try{ Connection conn = tl.get(); if(conn!=null){ conn.commit(); } }catch (Exception e) { throw new RuntimeException(e); } } public static Connection getConnection() throws SQLException{ try{ //得到当前线程上绑定的连接 Connection conn = tl.get(); if(conn==null){ //代表线程上没有绑定连接 conn = ds.getConnection(); tl.set(conn); } return conn; }catch (Exception e) { throw new RuntimeException(e); } } } //在服务层用上ThreadLocal的事务管理 public void transfer2(int sourceid,int targetid,double money) throws SQLException{ try{ JdbcUtils.startTransaction(); AccountDao dao = new AccountDao(); Account a = dao.find(sourceid); //select Account b = dao.find(targetid); //select a.setMoney(a.getMoney()-money); b.setMoney(b.getMoney()+money); dao.update(a); //update dao.update(b);//update JdbcUtils.commitTransaction(); }finally{ JdbcUtils.closeConnection(); } } } //持久层,获取绑定在当前线程上的connection,进行操作 public Account find(int id){ try{ QueryRunner runner = new QueryRunner(); String sql = "select * from account where id=?"; return (Account) runner.query(JdbcUtils.getConnection(),sql, id, new BeanHandler(Account.class)); }catch (Exception e) { throw new RuntimeException(e); } }
使用ThreadLocal应该注意的问题
在上面的代码中将ThreadLocal对象做成了静态private static ThreadLocal tl = new ThreadLocal(); //map
因此,每次开启一条线程,ThreadLocal都会有一个Connection加进来,所以,我们要记得将这些Connection移除,不然
这个ThreadLocal静态对象会越变越大,最后导致程序挂掉!!!!!!
-> 即,在关闭链接是,把变量移除
public static void closeConnection(){ try{ Connection conn = tl.get(); if(conn!=null){ conn.close(); } }catch (Exception e) { throw new RuntimeException(e); }finally{ tl.remove(); //千万注意,解除当前线程上绑定的链接(从threadlocal容器中移除对应当前线程的链接) } }
相关文章推荐
- hdoj 1052Tian Ji -- The Horse Racing 【贪心】
- lintcode-中位数-80
- ConcurrentHashMap 原理简要分析
- spring带来的春天
- iOS远程推送
- iOS:集合视图UICollectionView、集合视图控制器UICollectionViewController、集合视图单元格UICollectionViewCell(创建表格的另一种控件)
- 同一进程中的线程有哪些资源可以共享(转)
- 后缀自动机
- Python经常使用第三方工具、库、骨架
- Windows环境下Android Studio下载安装
- [BZOJ1637][Usaco2007 Mar]Balanced Lineup
- Gradle Android它自己的编译脚本教程的最新举措(提供demo源代码)
- Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 2)
- java 知识
- nginx优化
- 面向对象特性
- 赛码在线编程1001
- Android手机屏幕到手机间的距离
- oracle查看未提交事务
- Spring Framework 下载链接_现在有空