ThreadLocalの原理と例

2555 ワード

ThreadLocalはjavaオープンソースで非常に流行しているスレッド管理ツールクラスで、同時発生を防止し、効率を高めることができます.synchronizedを使うと、効率が悪いはずです.
ソースコードを見ると、その原理がわかりやすくなります.
public class ThreadLocal
{
 private Map values = Collections.synchronizedMap(new HashMap());
 public Object get()
 {
  Thread curThread = Thread.currentThread(); 
  Object o = values.get(curThread); 
  if (o == null && !values.containsKey(curThread))
  {
   o = initialValue();
   values.put(curThread, o); 
  }
  return o; 
 }

 public void set(Object newValue)
 {
  values.put(Thread.currentThread(), newValue);
 }

 public Object initialValue()
 {
  return null; 
 }
} 

このinitialValueメソッドに注意してください.私たちは一般的にこのメソッドを書き直します.
次に、インスタンスコードを示します.
public class StringThread extends Thread{
    private ThreadLocal tl;
    private String threadName;
    public StringThread(ThreadLocal tl, String threadName){
    	this.tl=tl;
    	this.threadName=threadName;
    }
	@Override
	public void run() {
		if(this.tl!=null){
			for(int i=0;i<3;i++){
				StringBuffer sb=(StringBuffer)this.tl.get();
				sb.append("run");
				System.out.println(this.threadName+":"+this.tl.get());
			}
			
		}
	}
    
}


public class ThreadLocalTest {
	private ThreadLocal tl=new ThreadLocal(){
		@Override
		public Object get() {
			return super.get();
		}
		@Override
		protected Object initialValue() {
			return new StringBuffer();
		}
		@Override
		public void remove() {
			super.remove();
		}
		@Override
		public void set(Object arg0) {
			super.set(arg0);
		}
		
	};
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ThreadLocalTest tlt=new ThreadLocalTest();
		StringThread st1=new StringThread(tlt.tl,"thread 1 ");
		StringThread st2=new StringThread(tlt.tl,"thread 2 ");
		StringThread st3=new StringThread(tlt.tl,"thread 3 ");
		
		st1.start();
		st2.start();
		st3.start();
	}

}

実行結果:
thread 3 :run
thread 2 :run
thread 1 :run
thread 2 :runrun
thread 3 :runrun
thread 2 :runrunrun
thread 1 :runrun
thread 3 :runrunrun
thread 1 :runrunrun