目的のThreadLocal?[重複]
-
18-09-2019 - |
質問
この質問に答えはこちら
の目的ThreadLocal指定された こちらの 状態の変数は、任意のスレッドにアクセスを含むオブジェクトですThreadLocal可変となります。何か違いはあり、有ThreadLocal変数の一員として、クラスおよびその後も地元のスレッドによる局所変数のスレッドです。
解決
のスレッドが実行の単位であるので、複数のスレッドが同時に同じコードを実行することができます。複数のスレッドが同時にオブジェクト/インスタンス上で実行した場合、それらはインスタンス変数を共有します。各スレッドは、独自のローカル変数を持つことになりますが、パラメータを渡すことなく、オブジェクト間でこれらを共有することは困難である。
これは、最良の例に説明されます。あなたはログインしているユーザーを取得し、いくつかのコードを実行されるサーブレットがあるとします。
doGet(HttpServletRequest req, HttpServletResponse resp) {
User user = getLoggedInUser(req);
doSomething()
doSomethingElse()
renderResponse(resp)
}
doSomethingの()メソッドは、ユーザーオブジェクトにアクセスする必要がある場合は、さてどうなりますか?あなたは、各スレッドが同じユーザオブジェクトを使用するので、ユーザーは、インスタンスまたは静的変数をオブジェクトにすることはできません。あなたは、パラメータとして周りのユーザーオブジェクトを渡すことができますが、これはすぐに乱雑になり、すべてのメソッド呼び出しにユーザーオブジェクトをリークします:
doGet(HttpServletRequest req, HttpServletResponse resp) {
User user = getLoggedInUser(req);
doSomething(user)
doSomethingElse(user)
renderResponse(resp,user)
}
よりエレガントな解決策は、ThreadLocalの
にユーザオブジェクトを置くことですdoGet(HttpServletRequest req, HttpServletResponse resp) {
User user = getLoggedInUser(req);
StaticClass.getThreadLocal().set(user)
try {
doSomething()
doSomethingElse()
renderResponse(resp)
}
finally {
StaticClass.getThreadLocal().remove()
}
}
これでいつでもユーザーオブジェクトを必要とするすべてのコードは、それらの厄介な追加パラメータに頼る必要がなく、地元のスレッドからそれを抽出して、それを手に入れることができます:
User user = StaticClass.getThreadLocal().get()
あなたがもう一度オブジェクトを削除するために注意して、このアプローチを使用する場合は、finallyブロック。それ以外の場合は、ユーザオブジェクトは、(Tomcatのアプリケーションサーバのような)スレッドプールを使用する環境でたむろすることがあります。
編集:静的クラスのコード
class StaticClass {
static private ThreadLocal<User> threadLocal = new ThreadLocal<>();
static ThreadLocal<User> getThreadLocal() {
return threadLocal;
}
}
他のヒント
いことを実現 クラスのインスタンスに至るスレッドが ない 同じものとして、実際のJavaのスレッド (できる想像として"実行ポインタ"を貫くコードを実行します。
インスタンスのクラス 代表 Javaのスレッドに許可を操作するので(例えば割り込み)がかかってきたので通常のオブジェ、その委員からアクセスできるすべてのスレッドで手への参照オブジェクトである ない).
もちろんできるようにしている会員の民間のいところを狙っていることを確認のみを使用する run()
やるからで(publicメソッドから呼び出すことができ他のスレッドとしても)、これはエラーが発生しやすいといを実現するためのより複雑なシステムによってお使いのデータを保持してすべてのスレッド内のサブクラス(実際にいうことになっているサブクラスはスレッドが使用Runnableます。
ThreadLocalは、柔軟ないスレッド単位のデータ できない アクセス同時にその他のスレッドによって、必要な力やデザインに妥協.
Threadオブジェクトは、内部データメンバを持つことができますが、これらはスレッドオブジェクトへの参照を持っている(または取得することができます)誰にでもアクセス可能です。 ThreadLocalのは、故意にのみ、それをアクセスする各スレッドに関連付けられています。利点は、(ThreadLocalののコンテキスト内で)は並行性の問題がないことです。スレッドの内部データメンバは、任意の共有状態が行うすべて同じ同時実行の問題があります。
私は特定のスレッドで結果を関連付けるの考えを説明しましょう。 ThreadLocalの本質は、このようなものです。
public class MyLocal<T> {
private final Map<Thread, T> values = new HashMap<Thread, T>();
public T get() {
return values.get(Thread.currentThread());
}
public void set(T t) {
values.put(Thread.currentThread(), t);
}
}
今そこにそれよりそれへ多くのですが、あなたは現在のスレッドによって決定され返された値を見ることができるように。それは、各スレッドにののローカル理由です。
ThreadLocalのは、webアプリケーションに非常に有用です。典型的なパターンはThreadLocal変数に格納されている状態(通常サーブレット・フィルタで)Webリクエストの処理の開始時に、そのどこかにあります。要求に対する処理のすべてが1つのスレッドで実行されているため、要求に参加しているすべてのコンポーネントは、この変数にアクセスすることができます。
との のではないスレッドセーフでJAVAのAPI構築物は、例えば、ある、忘れdonn't DateFormatのに。たDateFormatの静的インスタンスは、単にサーバー側では動作しません。
実際には、それはあなたがロックやモニターで扱うよりも、データの独自のプライベート・コピーを使用する場合、マルチスレッドプログラミングを処理する方が簡単です。
ThreadLocalsの利点は、プレーンバニラのスレッド...またはスレッドの任意のサブクラスで実行する方法で使用可能であるということです。
あなたのスレッドの地元の人々は、スレッドのカスタムサブクラスのメンバーとして実装する必要がある場合は、これとは対照的に、あなたが行うことができないものがたくさんあります。それは既存のバニラスレッドのインスタンスでメソッドを実行する必要がある場合たとえば、あなたのアプリケーションはトラブルになります。アプリケーションライターが書いていない、と変更できないことを、いくつかのライブラリのコードによって作成された、すなわちインスタンスます。