目次
1. 以前:
トランザクション制御を使用してビジネス機能を完了する
目的:スレッドの各コードでは、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.データベース接続、セッションセッション管理。
ThreadLocalのその他の注意点
ThreadLocalを紹介する記事は、1つのポイント、つまりメモリリークの問題を理解するのに役立ちます。まず下の写真を見てみましょう。
上の図は、ThreadLocalとThreadおよびThreadLocalMapの関係を詳細に示しています。
1. ThreadLocalMapであるThreadにマップがあります
2. ThreadLocalMapのキーはThreadLocalで、値は自分で設定します。
3. ThreadLocalは弱い参照であり、nullの場合、ガベージコレクションとして扱われます。
4.ここがポイントです。突然、ThreadLocalがnullになり、ガベージコレクターによってリサイクルされます。ただし、現時点では、ThreadLocalMapのライフサイクルはThreadと同じであるため、リサイクルされません。現時点では、現象が発生しています。つまり、ThreadLocalMapのキーはなくなりましたが、値はまだ残っているため、メモリリークが発生します。
解決策:ThreadLocalを使用した後、メモリオーバーフローを回避するために削除操作を実行します。
ツールのアップグレード
さて、次のステップはツールクラスをアップグレードすることで、焦点はThreadLocalを介して接続接続を最適化することです
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の使用前後
先立って: