ThreadLocalの浅い分析
4344 ワード
ThreadLocalって何?
JDK 1.2のバージョンではjavaが提供されています.lang.ThreadLocal,ThreadLocalはマルチスレッドプログラムの同時問題を解決するために新しい考え方を提供した.このツールクラスを使用すると、美しいマルチスレッドプログラムを簡潔に作成できます.java.lang.ThreadLocalはスレッドローカル(thread-local)変数を提供します.これらの変数は、ある変数(getメソッドまたはsetメソッドによって)にアクセスする各スレッドに独自のローカル変数があり、変数の初期化コピーとは独立しているため、通常の対応物とは異なります.ThreadLocalインスタンスは、通常、あるスレッド(例えば、ユーザIDまたはトランザクションID)にステータスを関連付けるクラスのprivate staticフィールドです.各スレッドは、スレッドがアクティブであり、ThreadLocalインスタンスがアクセス可能である限り、スレッドのローカル変数のコピーに対する暗黙的な参照を保持します.スレッドが消えた後、そのスレッドローカルインスタンスのすべてのコピーはGCによって回収されます(これらのコピーに対する他の参照がない限り).
ThreadLocalインタフェースメソッド
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
protected T initialValue() {
return null;
}
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
ソースコードの浅い分析
JDKのソースコードを分析するのは理解しにくいかもしれませんが、ThreadLocalクラスを簡略化することができます.簡略化されたコードは以下の通りです.
class MyThreadLocal{
private Map map = new HashMap();
protected T initialValue() {
return null;
}
public void set(T value) {
map.put(Thread.currentThread(), value);
}
public void remove() {
map.remove(Thread.currentThread());
}
public T get() {
return map.get(Thread.currentThread());
}
}
実際にはThreadLocal内部では1つのMapを維持してデータを保存するものであり、使用時に取得する値はvalue値であるが、それぞれのvalueに対応するkeyは現在のスレッドであるため、変数を各スレッドに1部コピーすることに相当し、各スレッドはデータの動作に相互に影響しない.
実用的なケース
私たちはデータベースを操作するとき、データセキュリティのためにトランザクション操作を加えなければならないことがありますが、一般的なトランザクション管理はService層にあり、データ操作はDAO層にあります.一般的な方法は、Service層に接続を確立してDAO層にパラメータを渡すことです.これはプログラムの侵入性を増加させるに違いありません.Springのトランザクション管理の下部ではThreadLocalを使用してこのような状況を解決しています.また、ThreadLocalを使用してトランザクション操作ツールクラスを記述することもシミュレーションできます.
public class JdbcUtils {
private static DataSource dataSource = new ComboPooledDataSource();
private static ThreadLocal tl = new ThreadLocal();
//
public static DataSource getDataSource() {
return dataSource;
}
//
public static Connection getConnection() throws SQLException {
Connection con = tl.get();
if(con == null) {
return dataSource.getConnection();
}
return con;
}
//
public static void beginTranscation() throws SQLException {
Connection con = tl.get();
if(con != null ) {
throw new SQLException(" , , !");
}
con = dataSource.getConnection();
con.setAutoCommit(false);
tl.set(con);
}
//
public static void commitTransaction() throws SQLException {
Connection con = tl.get();
if(con == null ) {
throw new SQLException(" , !");
}
con.commit();
con.close();
tl.remove();
}
//
public static void rollbackTransaction() throws SQLException {
Connection con = tl.get();
if(con == null) {
throw new SQLException(" , !");
}
con.rollback();
con.close();
tl.remove();
}
}