目录
1、之前:
使用事务控制完成业务功能
目的:在一个线程的各段代码中,只使用一个连接Conn
ThreadLocal功能:为同一个线程保存同一个值,为不同线程保存不同的值.
创建ThreadLocal对象,ThreadLocal<T> tdl = new ThreadLocal<T> ();
常用方法有:
测试代码如下:
package jdbc;
public class TestThreadLocal {
public static void main(String[] args) throws Exception {
//tl对象可以为同一个线程保存相同的值,为不同线程保存不同的值.
final ThreadLocal<String> tl = new ThreadLocal<String>();
Thread t1 = new Thread() {
public void run() {
tl.set("hello");
System.out.println("t1:" + tl.get());
}
};
t1.start();
Thread.sleep(1000);
Thread t2 = new Thread(){
public void run() {
tl.set("world");
System.out.println("t2:"+tl.get());
}
};
t2.start();
}
}
输出结果为:
ThreadLocald的常见使用场景
1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。
2、线程间数据隔离
3、进行事务操作,用于存储线程事务信息。
4、数据库连接,Session会话管理。
ThreadLocal其他几个注意的点
只要是介绍ThreadLocal的文章都会帮大家认识一个点,那就是内存泄漏问题。我们先来看下面这张图。
上面这张图详细的揭示了ThreadLocal和Thread以及ThreadLocalMap三者的关系。
1、Thread中有一个map,就是ThreadLocalMap
2、ThreadLocalMap的key是ThreadLocal,值是我们自己设定的。
3、ThreadLocal是一个弱引用,当为null时,会被当成垃圾回收
4、重点来了,突然我们ThreadLocal是null了,也就是要被垃圾回收器回收了,但是此时我们的ThreadLocalMap生命周期和Thread的一样,它不会回收,这时候就出现了一个现象。那就是ThreadLocalMap的key没了,但是value还在,这就造成了内存泄漏。
解决办法:使用完ThreadLocal后,执行remove操作,避免出现内存溢出情况。
工具类的升级
好吧,接下来就对,工具类进行升级了,重点是通过ThreadLocal对Connection连接进行优化
package util;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
/*
* jdbc工具类
* 1:properties配置文件 封装获取连接,释放资源,提高代码复用性
* 2:类加载时加载驱动
* 3:Threadlocal控制事务
* */
public class jdbcUtil2 {
//创建properties
static Properties pro = new Properties();
//创建Thread local<Connection>,可以为同一个线程保存同一个连接,为不同线程保存不同的连接
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
//加载驱动
static{
InputStream is = null;
try {
is = jdbcUtil.class.getResourceAsStream("/conf/db.properties");
pro.load(is);
Class.forName(pro.getProperty("driverClassName"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//获取连接
public static Connection getConnection() throws Exception{
Connection conn = tl.get();//获得当前线程中的连接
if(conn == null){//如果当前线程中没有连接
String url = pro.getProperty("url");
String user = "root";
String password = "root123";
//创建连接
conn = DriverManager.getConnection(url, user, password);
//将连接保存到当前线程
tl.set(conn);
}
return conn;
}
//释放资源/关闭连接
public static void release(ResultSet rs,PreparedStatement psm,Connection conn) throws SQLException{
if(rs!=null){
rs.close();
}
if(psm!=null){
psm.close();
}
if(conn!=null){
conn.close();
tl.remove();//将连接从当前线程中移出
}
}
}
用ThreadLocal之前与之后对比
之前:
之后
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114779.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...