JavaスレッドローカルストレージのThreadLocal

序文

  • 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>(l​​oadFactor、(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方法のハッシュマップの前に記載されています。

おすすめ

転載: www.cnblogs.com/aishangJava/p/11267562.html