Javaマルチスレッド――ThreadLocal


複数のスレッド間でリソースを共有する必要がある場合、スレッド間の通信は同期機構を使用することができる。複数のスレッド間の共有衝突を分離する必要がある場合、ThreadLocalを使用することができます。
 
public class ThreadLocal
extens Object
 
ThreadLocal類はスレッドローカル変数を提供します。ある変数(そのgetまたはset方法によって)にアクセスするスレッドごとに独自のローカル変数があります。ThreadLocalの例は、通常、クラス内のprvate staticフィールドであり、状態をあるスレッド(例えば、ユーザIDまたはトランザクションID)に関連付けることを望む。
 
 

  
  
  
  
  1. package example.thread.threadLocal; 
  2.  
  3. public class SerialNum { 
  4.  
  5.     private static int nextSerialNum = 1
  6.  
  7.     private static ThreadLocal<Integer> serialNum = new ThreadLocal<Integer>() { 
  8.         protected Integer initialValue() { 
  9.             return new Integer(nextSerialNum++);       
  10.         }                                                            
  11.     }; 
  12.  
  13.     public static int get() { 
  14.         return ((Integer) (serialNum.get())).intValue(); 
  15.     } 
  16.      
  17.  
  18.     public static void set(Integer newSerial){ 
  19.         serialNum.set(newSerial); 
  20.     } 
 
 

  
  
  
  
  1. package example.thread.threadLocal; 
  2.  
  3. public class GetSerialNumThread implements Runnable { 
  4.  
  5.     public static void main(String args[]) { 
  6.  
  7.         GetSerialNumThread serialNumGetter = new GetSerialNumThread(); 
  8.         Thread t1 = new Thread(serialNumGetter, "  A");  
  9.         Thread t2 = new Thread(serialNumGetter, "  B");  
  10.         Thread t3 = new Thread(serialNumGetter, "  C"); 
  11.         t1.start(); 
  12.         try { 
  13.             t1.join(); 
  14.         } catch (InterruptedException e) { 
  15.             e.printStackTrace(); 
  16.         }     
  17.         t2.start();  
  18.         t3.start(); 
  19.     } 
  20.  
  21.     public void run() { 
  22.         int mySerialNum = getSerialNum(); 
  23.         System.out.println(Thread.currentThread().getName() 
  24.                 + "  " + mySerialNum); 
  25.         System.out.println(Thread.currentThread().getName() 
  26.                 + "  " + (mySerialNum * 3)); 
  27.         setSerialNum(mySerialNum * 3); 
  28.         System.out.println(Thread.currentThread().getName() 
  29.                 + "  " + getSerialNum()); 
  30.     } 
  31.  
  32.     private int getSerialNum() { 
  33.         return SerialNum.get(); 
  34.     } 
  35.  
  36.     private void setSerialNum(int newSerialNum) { 
  37.         SerialNum.set(new Integer(newSerialNum)); 
  38.     } 
結果:
スレッドAが取得したシリアル番号は1です。
スレッドAがシリアル番号を3に変更しました。
スレッドAが再度取得したシリアルナンバーは3です。
スレッドBが取得したシリアル番号は2です。
スレッドBがシリアル番号を6に変更しました。
スレッドBが再度取得したシリアル番号は6です。
スレッドCが取得したシリアル番号は3です。
スレッドCはシリアル番号を9に変更しました。
スレッドCが再度取得したシリアルナンバーは9です。
 
上記の例から、スレッドごとに独自のThreadLocal変数があり、それらの値が互いに干渉しないことが分かります。これがThreadLocalの用途です。