序文
- ThreadLocalのは、 非同期 スレッドセーフな実装
- それは反映され
Thread-Specific Storage
たパターンを1つだけの入り口、内部は各スレッド固有のストレージスペースのために確保されます場合でも、スレッドが リソースを共有することはありません - 本論文では、要約されます
ThreadLocal
、私は助けることができる願って、使用方法および実装の詳細を
ThreadLocalのマインドマップ
スレッドのセキュリティダイアグラム
1.使用法
ThreadLocal
、使いやすいし ThreadLocal
、この記事が参照する、それは次のパブリックおよび保護された方法を提供しています android.os.Looper.java 説明する例として ThreadLocal
使用:
ThradlLocal UMLのクラス図
// /frameworks/base/core/java/android/os/Looper.java パブリッククラスルーパー{ // ... あなたが準備していない限り呼ば// sThreadLocal.getは())(nullを返します。静的最終ThreadLocalの<ルーパー> sThreadLocal = 新規のThreadLocal <ルーパー>(); プライベート静的ボイド(準備ブールquitAllowedを){ 場合(sThreadLocal。取得()!= NULL){ スロー(新規のRuntimeExceptionを"一つだけルーパーは、スレッドごとに作成することができます"); } //设置线程局部变量的值sThreadLocal。セット(新ルーパー(quitAllowed)); } パブリック静的ルーパーmyLooper(){ //获取线程局部变量的值
sThreadLocalを返します。取得する(); } パブリック静的ボイド(準備){(調製真)。} // ...}
ThreadLocal
ある のstatic final変数 、ジェネリックパラメータでありLooper
、の受け入れLooper
型の値Looper#prepare()
呼び出しThreadLocal#set()
設定 互いを上書きし、お互いを乱すことなく、変数の値の値をスレッドの異なるセットではなく、Looper#myLooper()
呼び出しThreadLocal#get()
取得 変数の値を、非干渉の値が異なるスレッドを取得します
Timethreads图 - 01
-
サブクラス 書き換え
ThreadLocal#initialValue()
、あなたは変数の初期値を設定することができ、我々はソースコードを表示します。公共のConcurrentHashMap (){ この(DEFAULT_INITIAL_CAPACITY、DEFAULT_LOAD_FACTOR、DEFAULT_CONCURRENCY_LEVEL)。 } 公共のConcurrentHashMap (INT InitialCapacityの値、フロートloadFactor、INTのconcurrencyLevel){ IF((loadFactor>!0)|| InitialCapacityの値< 0 ||のconcurrencyLevel <= 0)スロー(新しい、IllegalArgumentExceptionを)。(のconcurrencyLevel> MAX_SEGMENTS個)のconcurrencyLevel = MAX_SEGMENTS個であれば、// 2のべき乗のサイズに最も適合する引数を探すint型sshift = 0; int型ssize = 1; 一方、(ssize <のconcurrencyLevel){++ sshift。ssize << = 1。} = this.segmentShift 32 - sshift、セグメントの落下と判定された//ハイレベル、this.segmentMask = ssize - 1; //モジュロため。indexFor方法のハッシュマップの前に記載されています。-12のN乗; IF(InitialCapacityの値> MAXIMUM_CAPACITY)InitialCapacityの値= MAXIMUM_CAPACITY INT = InitialCapacityの値C / ssize; IF(C *をssize <InitialCapacityの値)++ C; INT = MIN_SEGMENT_TABLE_CAPACITY CAP; 一方(CAP <C)<< CAP = 1; //は、セグメントおよびセグメント[0]セグメント<K、V> S0 =作成する新しい新しいセグメント<K、V>(loadFactor、(INT)(* loadFactor CAP)を、(HashEntry <K、V> [])新しい新HashEntry [CAP]); //第1の位置セグメントセグメント<K、V> [] = SS(セグメント<K、V> [])を初期化新しい新しいセグメントを[ssize]; //初期化セグメントをUNSAFE.putOrderedObject(SS 、SBASE、セグメントの//順序付けられた書き込み[0] this.segments = SS。}
- では
ThreadLocal#get()
、変数の値を取得しようと、それが空の場合に呼び出されるThreadLocal#setInitialValue()
初期値設定します - 遅延初期化 :最初のコールがされるまで
get()
の初期値を設定することになります - デフォルト :初期値が設定されている ヌル
- では
-
ThreadLocal#remove()
以下のための 取り外し 前に変数を格納された値を。現在のスレッド次の呼び出しの場合はThreadLocal#get()
時間、何もset()
新しい値はまだ使用しませんThreadLocal#setInitialValue()
初期値を設定します。
ここでは、まとめることができ ThreadLocal
、以下に示すように、ライフサイクルを:
ライフサイクルのThreadLocalの図
2.プログラミング規程
覚えていますか?言及し、「アリ・ババのJava開発マニュアル」 ThreadLocal
規程のプログラミング、次のように:
-
5必須】
SimpleDateFormate
通常のように定義されていない、スレッドセーフなクラスではない 静的な 静的として定義されている場合、それはロックする必要があり、変数、または使用DateUtils
ツール正例:
プライベート静的最終ThreadLocalの<データフォーマット> DF = 新規のThreadLocal <たDateFormat>(){ @Overrideは DateFormatの保護はinitialValueが(){ 戻り(新しいてSimpleDateFormatを"YYYY-MM-DD")。}}。
説明:アプリケーションがJDK8であれば、使用することができる
Instant
代わりにDate
、LocalDateTime
代わりにCalendar
、DateTimeFormatter
代わりにSimpleDateFormat
、与えられた公式の説明:シンプルな美しい強い不変スレッドセーフ 。 -
15 [参考](原稿が長すぎるったらしいであり、以下の言い換え著者である)
ThreadLocal
変数を使用することをお勧めします 静的 変形を、クラスの変数の初期化を作成するために保証することができ、すべてのクラスのインスタンスは、同じ静的変数を共有します。気づきましたか?記事Looper.javaソースの先頭には、
ThreadLocal
変数が使用されstatic
修正します
私はあなたがマスターしていると信じて、ここを参照してください ThreadLocal
使用状況を、次の記事では掘り下げます ThreadLocal
データ構造の実装の詳細を探索する内部。
セグメント
ConcurrentHashMapのがセグメントの複数から構成されているセグメントは、すべてのロックがセグメントにある、ReentrantLockのを継承し、それは(また、サブロックとしても知られる)分離ロック役割を達成するために、他のセグメントには影響を与えないであろう。
各セグメントはまた、HashEntry配列が含まれている、HashEntryは、リンクされたリストです。下図のように:
concurrencyLevel:同時、デフォルト16、segmentShift及びsegmentMaskの値に直接影響し、初期セグメントの数。セグメントの初期化の数、及び2のN乗に等しい値に最も近いランよりも大きい、= 16のconcurrencyLevel例えば、セグメント16のconcurrencyLevel = 17、セグメント32の数の数。SegmentShift値は、2のパワーに対して、例えばセグメント32、5、次いで彼の値が上位5ビットを取ることである符号なし右シフト、後ろ時間27、27、32-5である、ようにされています0〜31の値は、下付き文字セグメントの場合は、弾性率は、各セグメントに対応する、0〜31です。図2は、ここで、segmentMask -1のn乗であるNモジュロ、5です。indexFor方法のハッシュマップの前に記載されています。