ホームページ >Java >&#&チュートリアル >Java での ThreadLocal の詳細な紹介 (コード例)
この記事では、Java の ThreadLocal について詳しく紹介 (コード例) しています。一定の参考価値があります。必要な友人は参照してください。お役に立てば幸いです。
ThreadLocal は基本的にプロジェクト開発では使用されませんが、面接官はこの種の質問を好むため、このクラスの機能と原理を理解しておく必要があります。
ThreadLocal とは
ThreadLocal は、複数のスレッドのスレッドごとに変数の個別のコピーを作成するクラスです。ThreadLocal を使用して変数を維持する場合、ThreadLocal は、複数のスレッドによって引き起こされるデータの不整合を避けるために、スレッドごとに変数の個別のコピーを作成します。共有変数のスレッド操作;
一般的に、ThreadLocal
は実際の工業生産では使用されません。一般的ですが、多くのフレームワークで使用すると、いくつかのフレームワークの問題を解決できます。たとえば、Spring のトランザクション、Spring のスコープ Scope
、Request の Bean
は、ThreadLocal.
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBConnectionFactory { private static final ThreadLocal<Connection> dbConnectionLocal = new ThreadLocal<Connection>() { @Override protected Connection initialValue() { try { return DriverManager.getConnection("", "", ""); } catch (SQLException e) { e.printStackTrace(); } return null; } }; public Connection getConnection() { return dbConnectionLocal.get(); } }このようにして、クライアントでは接続を取得するときに、各スレッドによって取得される接続はそのスレッドに固有であり、接続のスレッド分離が実現されるため、スレッドの安全性の問題は発生しません
#ThreadLocal がスレッドを実装する方法isolation
スレッドへの変数は次のとおりです:
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
1. まず現在の Thread オブジェクト t を取得し、次にスレッド t から ThreadLocalMap のメンバー属性 threadLocals
# を取得します。現在のスレッドが初期化されており (つまり、null ではなく)、現在の ThreadLocal オブジェクトをキーとして持つ値がある場合は、現在のスレッドによって取得されるオブジェクト (この例では Connection) を直接返します。
3. 現在のスレッドの threadLocals が初期化されている (つまり、null ではない) が、現在の ThreadLocal オブジェクトをキーとして持つオブジェクトがない場合は、Connection オブジェクトを再作成し、それを threadLocals に追加します。現在のスレッドのマップを返し、4 を返します。現在のスレッドの threadLocals プロパティが初期化されていない場合は、ThreadLocalMap オブジェクトを再作成し、Connection オブジェクトを作成して ThreadLocalMap オブジェクトに追加して返します。 存在する場合は、直接返されます。理解するのは簡単です。それでは、初期化方法のコードは何ですか?private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; }1. まず、作成したオーバーロードされたinitialValueメソッドを呼び出します。上記の操作により、Connection オブジェクトが生成されます。2. 現在のスレッドの threadLocals が空かどうかの確認を続けます。ThreadLocalMap が初期化されている場合は、生成されたオブジェクトを ThreadLocalMap に直接追加します。初期化されていない場合は、 ;同時に、ThreadLocal は Thread オブジェクト内の threadLocals を直接操作するメソッドも提供します
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }この方法では、initialValue を実装することもできません。 DBConnectionFactory の getConnection メソッドに初期化作業を追加します。
public Connection getConnection() { Connection connection = dbConnectionLocal.get(); if (connection == null) { try { connection = DriverManager.getConnection("", "", ""); dbConnectionLocal.set(connection); } catch (SQLException e) { e.printStackTrace(); } } return connection; }次に、コードを読むと、ThreadLocal が変数のマルチスレッド分離を実現できる理由が明確に理解できます。実際、これは Map データ構造を使用して、現在のスレッドをキャッシュし、それが使用されるときは、このスレッドからキャッシュされます。threadLocals オブジェクトから取得するだけで、キーは現在のスレッドになります。もちろん、現在のスレッドでマップし、現在のスレッドで操作すると、スレッドの同時実行の問題はまったく発生しません。もちろん変数も使用できます。スレッドは分離されます。 ThreadLocal とは何か、そしてその方法はわかりました。 ThreadLocal とその基本的な実装原則を使用しますが、これを終了してもよいでしょうか? 実際、もう 1 つの質問があります: ThreadLocalMap とは何ですか? オブジェクト、なぜこのオブジェクトを使用するのですか?ThreadLocalMap オブジェクトとは本質的に言ってみれば、これは Map ですが、この ThreadLocalMap は、私たちが通常見る Map とは少し異なります
# を継承します。 ##4. このメソッドは、キーと値を保存するためにエントリ配列のみを使用します。エントリはリンク リストの形式ではなく、各バケットに 1 つのエントリだけが配置されます。
以上がJava での ThreadLocal の詳細な紹介 (コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。