Java并发编程之ThreadLocal类详解

jopen 10年前
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