Java ThreadLocal の詳細
出典: Devgenios 今日は、Java アプリケーションの開発で使用される一般的なクラスの 1 つである ThreadLocal について学びます。スレッドローカルとは何ですか?
ThreadLocalクラスは、スレッドのローカル変数を格納します。これらの変数は異なるスレッド間で分離されており、独自のスレッドからのみアクセスできます。ThreadLocalの使用例:- スレッド間でデータを分離します。
- データベース接続のセッション管理。
- スレッドのトランザクション情報を保存します。
ThreadLocalの使い方は?
簡単な例を見てみましょう。public static void main(String[] args) {
//Создаем ThreadLocal
ThreadLocal<String> local = new ThreadLocal<>();
//Создаем новый класс Random
Random random = new Random();
//Создаем 5 потоков
IntStream.range(0, 5).forEach(a-> new Thread(()-> {
//Присваиваем meaning каждому потоку
local.set(a+" "+random.nextInt(100));
System.out.println("Thread number and its local value "+ local.get());
}).start());
}
上記のコードでは、 ThreadLocalクラス を作成し、5 つのスレッドを作成し、各スレッドでThreadLocalに値を割り当てて出力します。出力すると、次のようになります。
ボンネットの下には何があるのでしょうか?
よく見ると、このコード例からThreadLocalに2 つの重要なメソッドがあることがわかります。-
public T get() {}
-
パブリック void セット (T 値) {}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
setter メソッドは、まず現在のスレッドを取得し、getMap()メソッドを呼び出してThreadLocalMapクラスを取得します。マップが存在する場合は、現在のストリームt をキーとして、入力パラメータを値として取得し、{key:value}ペアをマップに設定します。そうでない場合は、マップを作成します。ここで、 「ThreadLocalMap とは何ですか?」 という質問があるかもしれません。
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
}
ThreadLocalMap は、データを格納するためのEntryクラスを定義するThreadLocalの内部静的クラスです。Entry はThreadLocalインスタンスをキーとして使用し、渡す値を設定します。この時点で非常に混乱しているように思われる場合は、実際に値を格納するのはThreadLocalMapのEntryクラスであることを思い出してください。ThreadLocalからデータを取得するには、getterメソッドを使用します。
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();
}
getterメソッド では、 ThreadLocalMap を取得するためのキーとしてcurrentThreadを使用します。次に、map はThreadLocalインスタンスに基づいてgetEntry()を実行し、Entryインスタンスと格納された値を返します。これを理解するのに役立つ図を次に示します。
-
各スレッドはThreadLocalMapへの参照を維持します。
-
ThreadLocalMap はThreadLocalの内部静的クラスであり、ストレージにEntryクラスを使用します。
-
ThreadLocalMapキーはThreadLocal のインスタンスであり、複数のThreadLocalを持つことができます。
-
ThreadLocal自体は値を保存しませんが、 ThreadLocalMapから値を取得するのに役立つスレッドのキーです。
Javaのスキャナクラス
出典: Medium この投稿は、Java の Scanner クラスに慣れるのに役立ちます。 Java のScannerクラスは、ユーザーから値を取得する場合に使用するクラスです。例を使って理解するのが最も簡単な方法なので、より明確に見てみましょう。Scannerクラスの作成は、ユーザーから値を取得するために実行する 3 つの手順のうちの 1 つです。最初のステップは、スキャナー クラスからオブジェクトを作成することです。Scanner scan=new Scanner(System.in);
これでスキャナーオブジェクトができました。このオブジェクトには、 Scannerクラスの Scanner プロパティが含まれます。最初のステップの後、ユーザーはすでに目的の値を入力できますが、ユーザーを誘導してコンソールやアプリケーションに値を表示しないと、ユーザビリティの点であまり良くありません。したがって、ユーザーに次のことを通知し、ガイドすることをお勧めします。
System.out.println("Please enter your name");
String name=scan.next();
System.out.println("Your Name:"+name);
最初の行では、ユーザーに何を望んでいるのかを尋ねます。これは実際にはスキャナとは関係ありませんが、ユーザーにヒントを与えることは常に良いことです。2 行目では、ユーザーがデータに入力した値を割り当て、後で使用できるように保存します。最後の行では、ユーザーから受け取った値を独自の裁量で使用できることがわかります。コードにさらに詳細を追加してみましょう。
System.out.println("Please enter your last name");
String lastName=scan.next();
System.out.println("Your Name " + name + " " + "Your Last Name" + lastName);
基本的に、前の 2 行を繰り返し、ユーザーに値を要求し、それを保存しました。最後の行では、ユーザーから取得した 2 つの値を使用し、現在は一緒に使用しています。
GO TO FULL VERSION