ThreadLocal (和线程绑定的map集合)
一.简述为什么要讲解ThreadLocal?为了项目解耦合,更好地维护项目耦合会使得项目维护难度增加解耦合。 直接去掉更多的importThreadLocal:本质MAP集合。绑定了线程的map集合。作用:在线程中进行数据共享。原理:一个ThreadLocal在一个线程中,只能保存一个键值对二.APIThreadLocal方法名描述set(Object o...
一.简述
为什么要讲解ThreadLocal?
- 为了项目解耦合,更好地维护项目
- 耦合会使得项目维护难度增加
- 解耦合。 直接去掉更多的import
ThreadLocal:本质MAP集合。
绑定了线程的map集合。
作用:在线程中进行数据共享。
原理:
- 一个ThreadLocal在一个线程中,只能保存一个键值对
二.API
ThreadLocal
方法名 |
描述 |
set(Object obj) |
为当前线程存放一个共享数据。 参数:Object 为共享数据。
第二次调用就是覆盖
相当于map.put(key,value); Key:是线程ID,无需程序员手动赋值。
|
get() |
获取当前线程的共享数据
返回值:Object 相当于map.get(key);
如果获取不到,返回为null |
remove() |
删除当前线程的共享数据
相当于map.remove(key);
|
public static void main(String[] args) {
//1、创建一个ThreadLocal对象
ThreadLocal<String> local = new ThreadLocal<String>();
//2、保存键值对,并取出展示
local.set("老王");
System.out.println(local.get());
//3、再次保存键值对,并取出展示
local.set("小王");//覆盖
System.out.println(local.get());
//4、删除键值对,并再尝试取出展示
local.remove();
System.out.println(local.get());
}
案例重构:转账案例
需求说明
Service需要和Connection对象解耦合。
解耦之后,service仍然可以正常进行提交和回滚。
需求分析
1、不能在service获取connection对象
(在JDBCUtils工具中,获取Connection时,设置为手动事务)
(在相同线程中 共享 Connection对象。 ThreadLocal)
2、dao的第一个参数没有Connection对象
3、在JDBCUtils中,写一个提交并关闭连接方法、回滚并关闭连接方法
代码实现
JDBCUtils
public class JDBCUtils {
public static final String DRIVERCLASS="com.mysql.jdbc.Driver";
public static final String URL="jdbc:mysql://127.0.0.1:3306/day03_db";
public static final String USERNAME="root";
public static final String PASSWORD="1234";
//定义好了一个绑定线程的map集合
private static final ThreadLocal<Connection> LOCAL = new ThreadLocal<Connection>();
static{
//1、注册驱动
try {
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/*
* 获取连接:
* 原则:1、同一个线程中,使用同一个Connection对象
* 2、每次获取到的Connection对象,都开启了 手动事务
* */
public static Connection getConnection() throws SQLException {
//1、尝试从ThreadLocal中获取,当前线程共享的connection
Connection con = LOCAL.get();
//2、如果当前线程没有绑定connection对象,创建connection对象,保存到threadLocal中
if(con==null){
//2.1、创建con对象
con = DriverManager.getConnection(URL,USERNAME,PASSWORD);
//2.2、开启手动事务
con.setAutoCommit(false);
//2.3、绑定到当前线程中,保存到ThreadLocal中
LOCAL.set(con);
}
return con;
}
/*
* 关闭资源
* */
public static void closeAll(Connection con, PreparedStatement ps, ResultSet rs) throws SQLException {
if(rs!=null)
rs.close();
if(ps!=null)
ps.close();
if(con!=null){
//1、先从当前线程解绑
LOCAL.remove();
//2、关闭资源
con.close();
}
}
/**
* 提交事务,并关闭资源
*/
public static void commitAndClose(){
//1、先尝试从ThreadLocal中获取con对象
Connection con = LOCAL.get();
//2、如果能获取到con,提交事务,并关闭资源
if(con!=null){
try {
con.commit();
closeAll(con,null,null);
} catch (SQLException e) {
}
}
}
/**
* 回滚事务,并关闭资源
*/
public static void rollbackAndClose(){
//1、先尝试从ThreadLocal中获取con对象
Connection con = LOCAL.get();
//2、如果能获取到con,回滚事务,并关闭资源
if(con!=null){
try {
con.rollback();
closeAll(con,null,null);
} catch (SQLException e) {
}
}
}
}
AccountService
public class AccountService {
private AccountDao dao = new AccountDao();
/**
* 转账功能
* @param userIn
* @param userOut
* @param money
* @return
*/
public boolean account(String userIn, String userOut, double money) {
try {
//1、付款人 付款
dao.userOut(userOut, money);
// int a = 1 / 0;
//2、收款人 收款
dao.userIn(userIn, money);
//没出异常,提交
JDBCUtils.commitAndClose();
} catch (Exception e) {
//出了异常,转账失败
JDBCUtils.rollbackAndClose();
return false;
}
//没出异常,转账成功
return true;
}
}
AccountDao
/**
* 付款人 付款
* @param userOut
* @param money
*/
public void userOut(String userOut, double money) throws SQLException {
//1、获取连接
Connection con = JDBCUtils.getConnection();
//2、获取发送SQL语句对象
PreparedStatement ps = con.prepareStatement("update account set money=money-? where name=?");
ps.setDouble(1,money);
ps.setString(2,userOut);
//3、发送SQL语句
ps.executeUpdate();
//4、关闭资源
JDBCUtils.closeAll(null,ps,null);
}
/**
* 收款人 收款
* @param userIn
* @param money
*/
public void userIn(String userIn, double money) throws SQLException {
//1、获取连接
Connection con = JDBCUtils.getConnection();
//2、获取发送SQL语句对象
PreparedStatement ps = con.prepareStatement("update account set money=money+? where name=?");
ps.setDouble(1,money);
ps.setString(2,userIn);
//3、发送SQL语句
ps.executeUpdate();
//4、关闭资源
JDBCUtils.closeAll(null,ps,null);
}
看完恭喜你,又知道了一点点!!!
你知道的越多,不知道的越多!
~感谢志同道合的你阅读, 你的支持是我学习的最大动力 ! 加油 ,陌生人一起努力,共勉!!
更多推荐
所有评论(0)