Java并发编程之ThreadLocal类详解

74 阅读1分钟

ThreadLocal类可以理解为 ThreadLocalVariable (线程局部变量) , 提供了get与set等访问接口或方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回当前执行线程在调用set时设置的最新值。可以将ThreadLocal<T>视为 包含了Map<Thread,T>对象,保存了特定于该线程的值。

概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

模拟ThreadLocal

     

       import java.util.Collections;
      

      

       import java.util.HashMap;
      

      

       import java.util.Map;
      

      

        
      

      

       public class SimpleThreadLocal<T> {
      

      

       	private Map<Thread, T> valueMap = Collections
      

      

       			.synchronizedMap(new HashMap<Thread, T>());
      

      

        
      

      

       	public void set(T newValue) {
      

      

       		valueMap.put(Thread.currentThread(), newValue); // ①键为线程对象,值为本线程的变量副本
      

      

       	}
      

      

        
      

      

       	public T get() {
      

      

       		Thread currentThread = Thread.currentThread();
      

      

       		T o = valueMap.get(currentThread); // ②返回本线程对应的变量
      

      

       		if (o == null && !valueMap.containsKey(currentThread)) { // ③如果在Map中不存在,放到Map中保存起来。
      

      

       			o = initialValue();
      

      

       			valueMap.put(currentThread, o);
      

      

       		}
      

      

       		return o;
      

      

       	}
      

      

        
      

      

       	public void remove() {
      

      

       		valueMap.remove(Thread.currentThread());
      

      

       	}
      

      

        
      

      

       	protected T initialValue() {
      

      

       		return null;
      

      

       	}
      

      

       }
      

     

实用ThreadLocal

     

       class Count {
      

      

       	private SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() {
      

      

       		@Override
      

      

       		protected Integer initialValue() {
      

      

       			return 0;
      

      

       		}
      

      

       	};
      

      

        
      

      

       	public Integer increase() {
      

      

       		count.set(count.get() + 1);
      

      

       		return count.get();
      

      

       	}
      

      

        
      

      

       }
      

      

        
      

      

       class TestThread implements Runnable {
      

      

       	private Count count;
      

      

        
      

      

       	public TestThread(Count count) {
      

      

       		this.count = count;
      

      

       	}
      

      

        
      

      

       	@Override
      

      

       	public void run() {
      

      

       		// TODO Auto-generated method stub
      

      

       		for (int i = 1; i <= 3; i++) {
      

      

       			System.out.println(Thread.currentThread().getName() + "\t" + i
      

      

       					+ "th\t" + count.increase());
      

      

       		}
      

      

       	}
      

      

       }
      

      

        
      

      

       public class TestThreadLocal {
      

      

       	public static void main(String[] args) {
      

      

       		Count count = new Count();
      

      

       		Thread t1 = new Thread(new TestThread(count));
      

      

       		Thread t2 = new Thread(new TestThread(count));
      

      

       		Thread t3 = new Thread(new TestThread(count));
      

      

       		Thread t4 = new Thread(new TestThread(count));
      

      

       		t1.start();
      

      

       		t2.start();
      

      

       		t3.start();
      

      

       		t4.start();
      

      

       	}
      

      

       }
      

      

       

      

     

输出\

Thread-0    1th    1

Thread-0    2th    2

Thread-0    3th    3

Thread-3    1th    1

Thread-1    1th    1

Thread-1    2th    2

Thread-2    1th    1

Thread-1    3th    3

Thread-3    2th    2

Thread-3    3th    3

Thread-2    2th    2

Thread-2    3th    3  

\