ThreadLocal的介绍与运用( 五 )

? (2) AccountService类的修改:不需要传递connection对象
package com.itheima.transfer.service;import com.itheima.transfer.dao.AccountDao;import com.itheima.transfer.utils.JdbcUtils;import java.sql.Connection;public class AccountService {public boolean transfer(String outUser, String inUser, int money) {AccountDao ad = new AccountDao();try {Connection conn = JdbcUtils.getConnection();//开启事务conn.setAutoCommit(false);// 转出 : 这里不需要传参了 !ad.out(outUser, money);// 模拟转账过程中的异常//int i = 1 / 0;// 转入ad.in(inUser, money);//事务提交JdbcUtils.commitAndClose();} catch (Exception e) {e.printStackTrace();//事务回滚JdbcUtils.rollbackAndClose();return false;}return true;}}? (3) AccountDao类的修改:照常使用
package com.itheima.transfer.dao;import com.itheima.transfer.utils.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;public class AccountDao {public void out(String outUser, int money) throws SQLException {String sql = "update account set money = money - ? where name = ?";Connection conn = JdbcUtils.getConnection();PreparedStatement pstm = conn.prepareStatement(sql);pstm.setInt(1,money);pstm.setString(2,outUser);pstm.executeUpdate();//照常使用//JdbcUtils.release(pstm,conn);JdbcUtils.release(pstm);}public void in(String inUser, int money) throws SQLException {String sql = "update account set money = money + ? where name = ?";Connection conn = JdbcUtils.getConnection();PreparedStatement pstm = conn.prepareStatement(sql);pstm.setInt(1,money);pstm.setString(2,inUser);pstm.executeUpdate();//JdbcUtils.release(pstm,conn);JdbcUtils.release(pstm);}}2.3.2 ThreadLocal方案的好处从上述的案例中我们可以看到 ,  在一些特定场景下 , ThreadLocal方案有两个突出的优势:

  1. 传递数据 : 保存每个线程绑定的数据 , 在需要的地方可以直接获取, 避免参数直接传递带来的代码耦合问题
  2. 线程隔离 : 各线程之间的数据相互隔离却又具备并发性 , 避免同步方式带来的性能损失
3. ThreadLocal的内部结构? 通过以上的学习 , 我们对ThreadLocal的作用有了一定的认识 。现在我们一起来看一下ThreadLocal的内部结构 , 探究它能够实现线程数据隔离的原理 。
3.1常见的误解? 通常 , 如果我们不去看源代码的话 , 我猜ThreadLocal是这样子设计的:每个ThreadLocal类都创建一个Map , 然后用线程的ID threadID作为Mapkey , 要存储的局部变量作为Mapvalue , 这样就能达到各个线程的局部变量隔离的效果 。这是最简单的设计方法 , JDK最早期的ThreadLocal就是这样设计的 。
3.2核心结构? 但是 , JDK后面优化了设计方案 , 现时JDK8 ThreadLocal的设计是:每个Thread维护一个ThreadLocalMap哈希表 , 这个哈希表的keyThreadLocal实例本身 , value才是真正要存储的值Object
? (1) 每个Thread线程内部都有一个Map (ThreadLocalMap)? (2) Map里面存储ThreadLocal对象(key)和线程的变量副本(value)? (3)Thread内部的Map是由ThreadLocal维护的 , 由ThreadLocal负责向map获取和设置线程的变量值 。? (4)对于不同的线程 , 每次获取副本值时 , 别的线程并不能获取到当前线程的副本值 , 形成了副本的隔离 , 互不干扰 。
ThreadLocal的介绍与运用

文章插图
3.3 这样设计的好处? 这个设计与我们一开始说的设计刚好相反 , 这样设计有如下两个优势:

经验总结扩展阅读