ホームページ  >  記事  >  Java  >  JavaマルチスレッドにおけるInheritableThreadLocalの詳細な説明

JavaマルチスレッドにおけるInheritableThreadLocalの詳細な説明

黄舟
黄舟オリジナル
2017-10-19 10:00:461982ブラウズ

この記事では主に Java マルチスレッド プログラミングの InheritableThreadLocal について詳しく紹介します。興味のある方は参考にしてください。

InheritableThreadLocal の役割: 子スレッドで親スレッドを使用する必要があるとき。 ThreadLocal と同様に InheritableThreadLocal を使用できます。

まず、InheritableThreadLocal の jdk ソース コードを見てみましょう:


package java.lang;
import java.lang.ref.*;

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
  protected T childValue(T parentValue) {
    return parentValue;
  }

  ThreadLocalMap getMap(Thread t) {
    return t.inheritableThreadLocals;
  }

  void createMap(Thread t, T firstValue) {
    t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
  }
}

このコードは、InheritableThreadLocal の完全なソース コードです (長いコメントは削除されています)。

まず、ThreadLocal クラスを継承し、以下を提供していることがわかります:

protected T childValue(TparentValue){} メソッド。これは InheritableThreadLocal へのキーであり、このメソッドを提供し、親スレッドに戻ります。 value に加えて、親スレッドにも値を追加する必要がある場合は、childValue メソッドをオーバーライドできます。


package InheritableThreadLocal;

import java.util.Date;

public class InheritableThreadLocaExt extends InheritableThreadLocal{
  protected Object initialValue() {
    return new Date().getTime();

  }
  protected Object childValue(Object parentValue) {
    return parentValue+"对继承值进行修改";

  }

}

package InheritableThreadLocal;

public class tool {
  public static InheritableThreadLocaExt t=new InheritableThreadLocaExt();

}

package InheritableThreadLocal;

public class MyThread extends Thread{

  public void run() {
      try {
        for(int i=0;i<10;i++) {
          System.out.println("在线程A中:"+tool.t.get());
        sleep(100);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }  
}

package InheritableThreadLocal;

public class test {
  public static void main(String[] args) {
    try {
      for(int i=0;i<10;i++) {
        System.out.println("主线程中值:"+tool.t.get());
        Thread.sleep(100);
      }
      Thread.sleep(5000);
      MyThread thread=new MyThread();
      thread.start();

    }catch(InterruptedException e){
      e.printStackTrace();
    }
  }
}

実行出力:

メインスレッド中央値: 1508210392057
メインスレッド中央値: 1508210392057
メインスレッド中央値: 1508210 3920 57
メインスレッドの中央値: 1508210392057
メインスレッドの値: 1508210392057
メインスレッド中央値: 1508210392057
メインスレッド中央値: 1508210392057
メインスレッド中央値: 1508210392057
スレッド A: 150821039 2057 継承値を変更します
スレッド A: 1508210392057 継承値を変更します
スレッド A: 1508210392057 を変更します継承された値
スレッド A 内: 1508210392057 継承された値を変更します
スレッド A 内: 1508210392057 継承された値を変更します
スレッド A 内: 1508210392057 継承された値を変更します 値が変更されます
スレッド A 内: 1508210392057 継承された値が変更されます
でスレッド A: 1508210392057 継承された値が変更されました
スレッド A: 1508210392057 継承された値が変更されました
スレッド A: 1508210392057 継承された値が変更されました 変更


質問がありますか、なぜ子スレッドは次のデータを取得できるのですか親スレッドは?


InheritableThreadLocal が getMap メソッドと createMap メソッドを書き換えていることがわかります。前のセクションで ThreadLocal について説明したとき、ThreadLocal の値は ThreadLocals という変数に格納されることがわかりましたが、今度は InheritableThreadLocals This 変数を返します。名前が変更されていることを除いて、これらはまったく同じですが、なぜ新しいスレッドでも threadlocal.get() メソッドを通じて値を取得できるのでしょうか。


childValue メソッドを見ると、スレッドの作成時に何らかのトリックが行われ、いくつかの値が渡されたのではないかと推測できます。


Thread クラスのソース コードを開くと、次のことがわかります:


ThreadLocal.ThreadLocalMap respectableThreadLocals = null;


したがって、子スレッドを作成すると、同じ InheritableThreadLocal 変数が含まれます。 ThreadLocals として、さらに下を見てください:

private void init(ThreadGroup g, Runnable target, String name,
           long stackSize, AccessControlContext acc,
           .
           .
           if (inheritThreadLocals && parent.inheritableThreadLocals != null)
      this.inheritableThreadLocals =
        ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

重要な点は次のコードです:

if (inheritThreadLocals && parent.inheritableThreadLocals != null)
      this.inheritableThreadLocals =
        ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

引き続き見てください:


 static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
    return new ThreadLocalMap(parentMap);
  }

private ThreadLocalMap(ThreadLocalMap parentMap) {
      Entry[] parentTable = parentMap.table;
      int len = parentTable.length;
      setThreshold(len);
      table = new Entry[len];

      for (int j = 0; j < len; j++) {
        Entry e = parentTable[j];
        if (e != null) {
          @SuppressWarnings("unchecked")
          ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
          if (key != null) {
            Object value = key.childValue(e.value);
            Entry c = new Entry(key, value);
            int h = key.threadLocalHashCode & (len - 1);
            while (table[h] != null)
              h = nextIndex(h, len);
            table[h] = c;
            size++;
          }
        }
      }
    }

このコードでは、最初に親を取得しますthread (これは現在実行中のスレッドの値でもあります)、次に for ループを使用して、親スレッドの値を新しく作成した値に 1 つずつ入れます。

以上がJavaマルチスレッドにおけるInheritableThreadLocalの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。