スレッド閉鎖のThreadLocalとスタック閉鎖


スレッド閉鎖
共有データにアクセスする場合、通常は同期を使用します.同期を使用しないようにするには、共有データは提供されません.単一スレッドでのみデータにアクセスする場合、同期を必要としない技術をスレッド閉鎖と呼び、スレッドセキュリティを実現する最も簡単な方法の一つです.あるオブジェクトが1つのスレッドに閉じ込められると、自動的にスレッドセキュリティが実現されます.閉じ込められたオブジェクト自体がセキュリティではなくても、実装スレッドには主に3つの方法があります.
 
Ad-hocスレッド閉鎖
 
Ad-hocとは、メンテナンススレッドの閉鎖がプログラム自身で実現され、メンテナンスされることを指す.Ad-hocは、可視性修飾子やローカル変数などの言語特性がないため、特定のスレッドにオブジェクトを閉じることができます.
 
スタック閉鎖
 
スタック閉鎖の簡単な理解は、ローカル変数によってスレッド閉鎖を実現することであり、複数のスレッドがオブジェクトにアクセスする同じ方法であり、方法内部のローカル変数は各スレッドのスレッドスタックにコピーされ、現在のスレッドだけがアクセスでき、互いに干渉しない.したがって、ローカル変数は複数のスレッドで共有されません.
例:
public class ThreadTest {
    private int num;
    public void test(int key){
        int flag=0;
        for(int i=0;i

例から分かるように、クラスにはグローバル変数numがあり、メソッドにはローカル変数flagがあり、2つのスレッドを起動してこのメソッドを呼び出すと、numの結果は2つのスレッド結果の和であり、flagは互いに干渉しないため、ローカル変数は複数のスレッドで共有されないことが分かった.
 
 ThreadLocal
 
スレッド閉鎖を維持するより規範的な方法はThreadLocalを使用することです.ThreadLocalは、変数を使用するスレッドごとに独立したコピーを格納するgetメソッドとsetメソッドを提供します.したがって、getは常に現在のスレッドがsetを呼び出すときに設定された値を返します.
 
ThreadLocalは一般に、可変の単一インスタンス変数またはグローバル変数の共有を防止するために使用される.たとえば、単一スレッド・アプリケーションでは、グローバルなデータベース接続が維持され、プログラムの起動時にオブジェクトが初期化されるため、呼び出しの各メソッドでConnectionオブジェクトが渡されないようにします.JDBCの接続先は、必ずしもスレッドセキュリティではないため、マルチスレッドアプリケーションが連携していない場合にグローバル変数を使用する場合、スレッドセキュリティではなく、JDBCの接続をThreadLocalに保存することで、各スレッドは独自の接続を持つことになる.
ThreadLocalコードの例:
/**        */
public class Demo7 {
    /** threadLocal  ,          ,     */
    public static ThreadLocal value = new ThreadLocal<>();

    /**
     * threadlocal  
     *
     * @throws Exception
     */
    public void threadLocalTest() throws Exception {

        // threadlocal      
        value.set("        123"); //       
        String v = value.get();
        System.out.println("  1    ,       :" + v);

        new Thread(new Runnable() {
            @Override
            public void run() {
                String v = value.get();
                System.out.println("  1    :" + v);
                //    threadLocal
                value.set("    1   456");

                v = value.get();
                System.out.println("      ,  1    :" + v);
                System.out.println("  1    ");
            }
        }).start();
        Thread.sleep(5000L); //           
        v = value.get();
        System.out.println("  1    ,       :" + v);

    }

    public static void main(String[] args) throws Exception {
        new Demo7().threadLocalTest();
    }
}
#   
  1    ,       :        123
  1    :null
      ,  1    :    1   456
  1    
  1    ,       :        123

コード例では、プライマリ・スレッドとサブスレッドの実行結果が互いに干渉しないことがわかります.頻繁に実行される操作にバッファなどの一時オブジェクトが必要であり、実行するたびに一時オブジェクトを再割り当てしないようにするには、ThreadLocalを使用します.