スレッドのThreadLocal

5253 ワード

1.まず、ThreadLocal以外の例を見てみましょう

package thread;

/**
 */
public class ThreadLocalDemo {
	
    public ThreadLocalDemo() {};
    
    //  ThreadLocal initialValue() , 
    private static int seqNum = 0;
    
    //  
    public int getNextNum() {
    	
        return ++seqNum;
    }
    
    public static void main(String[] args) {
        
    	ThreadLocalDemo test = new ThreadLocalDemo();
        
        // 3 sn, 
    	TestClientDemo client1 = new TestClientDemo(test);
    	TestClientDemo client2 = new TestClientDemo(test);
    	TestClientDemo client3 = new TestClientDemo(test);
        
        client1.start();
        client2.start();
        client3.start();
    }
}
class TestClientDemo extends Thread {
    
    private ThreadLocalDemo test;
    
    /**
     *  .
     */
    public TestClientDemo() {};
    
    /**
     *  .
     */
    public TestClientDemo(ThreadLocalDemo test) {
        
        this.test = test;
    };
    
    @Override
    public void run() {
        
        //{④ 3 
        for(int i=0 ; i<=3 ; i++) {
            
            System.err.println(Thread.currentThread().getName() + "===NextNum is:==" +test.getNextNum());
        }
    }
}

これは、5つのスレッドが静的変数threadNameにアクセスする例であり、出力を見てみましょう.
Thread-0===NextNum is:==1
Thread-0===NextNum is:==2
Thread-0===NextNum is:==3
Thread-0===NextNum is:==4
Thread-1===NextNum is:==5
Thread-1===NextNum is:==6
Thread-1===NextNum is:==7
Thread-1===NextNum is:==8
Thread-2===NextNum is:==9
Thread-2===NextNum is:==10
Thread-2===NextNum is:==11
Thread-2===NextNum is:==12
3つのスレッドが1つのseqNumを共有していることがわかる.
2.ThreadLocalの例をもう一つ見てみましょう
package thread;

/**
 */
public class ThreadLocalCamp {
	
    public ThreadLocalCamp() {};
    
    //  ThreadLocal initialValue() , 
    private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {     
        protected Integer initialValue() {
            return 0;
        }
    };
    
    //  
    public int getNextNum() {
        
        seqNum.set(seqNum.get()+1);
        return seqNum.get();
    }
    
    public static void main(String[] args) {
        
    	ThreadLocalCamp test = new ThreadLocalCamp();
        
        // 3 sn, 
        TestClient client1 = new TestClient(test);
        TestClient client2 = new TestClient(test);
        TestClient client3 = new TestClient(test);
        
        client1.start();
        client2.start();
        client3.start();
    }
}
class TestClient extends Thread {
    
    private ThreadLocalCamp test;
    
    /**
     *  .
     */
    public TestClient() {};
    
    /**
     *  .
     */
    public TestClient(ThreadLocalCamp test) {
        
        this.test = test;
    };
    
    @Override
    public void run() {
        
        //{④ 3 
        for(int i=0 ; i<=3 ; i++) {
            
            System.err.println(Thread.currentThread().getName() + "===NextNum is:==" +test.getNextNum());
        }
    }
}

この2つのクラスの違いは、2番目のクラスのseqNumがThreadLocalを使用していることです.
private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {     
        protected Integer initialValue() {
            return 0;
        }
    };

2番目のクラスの出力を見てみましょう.
Thread-0===NextNum is:==1
Thread-2===NextNum is:==1
Thread-1===NextNum is:==1
Thread-2===NextNum is:==2
Thread-0===NextNum is:==2
Thread-2===NextNum is:==3
Thread-1===NextNum is:==2
Thread-2===NextNum is:==4
Thread-0===NextNum is:==3
Thread-0===NextNum is:==4
Thread-1===NextNum is:==3
Thread-1===NextNum is:==4
3つのスレッドにそれぞれ1つのseqNumがあることがわかる.
3.まとめ
このクラスは、スレッドローカル(thread-local)変数を提供します.これらの変数は、ある変数(getメソッドまたはsetメソッドによって)にアクセスする各スレッドに独自のローカル変数があり、変数の初期化コピーとは独立しているため、通常の対応物とは異なります.ThreadLocalインスタンスは、通常、あるスレッド(例えば、ユーザIDまたはトランザクションID)にステータスを関連付けるクラスのprivate staticフィールドです.
APIは以下のいくつかの観点を表している.
1、ThreadLocalはスレッドではなく、スレッドの変数であり、スレッドクラスの属性変数として簡単に理解することができます.
2、ThreadLocalはクラスで通常静的クラス変数として定義される.
3、各スレッドには独自のThreadLocalがあり、変数の「コピー」であり、他のスレッドに影響を与えないように変更されます.
クラス変数として定義されている以上、スレッドごとにコピーを維持し(一応「コピー」として理解しやすい)、スレッドごとに独立してアクセスできるようにするのはなぜですか?マルチスレッドプログラミングの経験は、スレッド共有リソース(属性として理解できる)について、リソースがすべてのスレッドで共有されているかどうか、すなわち、このリソースが1つのスレッドによって変更されて別のスレッドの実行に影響を与えるかどうか、影響を与える場合はsynchronized同期を使用してスレッドを順次アクセスさせる必要があることを示しています.
ThreadLocalは、リソースが共有されているが、ステータスを維持する必要がない場合に適用されます.つまり、1つのスレッドがリソースを変更し、別のスレッドの実行に影響を与えません.この設計は「空間交換時間」であり、synchronizedシーケンス実行は「時間交換空間」である.