package com.bdg.threadlocal;
import java.util.HashMap;
import java.util.Map;
/**
* 自定义一个ThreadLocal类
*/
public class MyThreadLocal<T> {
/**
* 所有需要和当前线程绑定的数据都要放到这个容器中
*/
private final Map<Thread, T> map = new HashMap<>();
/**
* 向ThreadLocal中绑定元素
* @param obj
*/
public void set(T obj) {
map.put(Thread.currentThread(), obj);
}
/**
* 从ThreadLocal中取元素
* @return
*/
public T get() {
return map.get(Thread.currentThread());
}
/**
* 移除ThreadLocal中的元素
*/
public void remove() {
map.remove(Thread.currentThread());
}
}
package com.bdg.threadlocal;
public class Connection {}
package com.bdg.threadlocal;
public class DBUtil {
//静态变量类加载时执行,并且只执行一次
//全局的大map
/*所有需要与线程绑定的数据的大容器*/
private static final MyThreadLocal<Connection> local = new MyThreadLocal<>();
/**
* 每一次都调用这个方法来获取Connection对象
*/
public static Connection getConnection() {
Connection conn = local.get();
if (conn == null) {
//第一次调用getConnection方法时conn一定是null.
//空的就需要new
conn = new Connection();
//将new出来的conn对象绑定到大map中
local.set(conn);
}
return conn;
}
}
package com.bdg.threadlocal;
public class UserDao {
public void insert() {
Thread thread = Thread.currentThread();
System.out.println(thread);
Connection conn = DBUtil.getConnection();
System.out.println(conn);
System.out.println("User DAO insert");
}
}
package com.bdg.threadlocal;
public class UserService {
private UserDao userDao = new UserDao();
public void save() {
Thread thread = Thread.currentThread();
System.out.println(thread);
Connection conn = DBUtil.getConnection();
System.out.println(conn);
userDao.insert();
}
}
package com.bdg.threadlocal;
public class Test {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
System.out.println(thread);
//调用service
UserService userService = new UserService();
userService.save();
}
}

public class DBUtil {
private static ResourceBundle bundle = ResourceBundle.getBundle("resources/jdbc");
private static String driver = bundle.getString("driver");
private static String url = bundle.getString("url");
private static String user = bundle.getString("user");
private static String password = bundle.getString("password");
private static ThreadLocal<Connection> local = new ThreadLocal<>();
//不然创建对象,因为工具类中的方法都是静态的,不需要创建对象。
//为了防止创建对象,故将构造方法私有化
private DBUtil() {}
//DBUtil类加载时注册驱动
static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//这里没有使用数据库连接池,直接创建连接对象
public static Connection getConnection() throws SQLException {
Connection conn = local.get();
if (conn == null) {
conn = DriverManager.getConnection(url, user, password);
local.set(conn);
}
System.out.println(conn);
return conn;
}
public static void close (Connection conn, Statement stmt, ResultSet rs) {
if (conn != null) {
try {
conn.close();
//Tomcat是支持多线程的,假设张三使用了T1连接对象,其他的用户也可能使用T1连接对象
local.remove();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}