早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本.
最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等.
2.部分源码
ThreadLocal中存在ThreadLocalMap 以不同的线程key创建不同的副本。如下ThreadLocal set() /get()方法
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }
3.代码实例
/** * Created by wuhao on 15-12-23. */ public class ThreadLocalDemo { public static void main(String[] args) { ThreadStringSeq tss = new ThreadStringSeq(); tss.setState("first"); //切换state ThreadStringClient ts1 = new ThreadStringClient(tss); ThreadStringClient ts2 = new ThreadStringClient(tss); new Thread(ts1).start(); new Thread(ts2).start(); ThreadLocalSeq tls = new ThreadLocalSeq(); System.out.println("Main:" + Thread.currentThread().getName() + " sn:" + tls.getNextState()); //切换state ThreadLocalClient tl1 = new ThreadLocalClient(tls); ThreadLocalClient tl2 = new ThreadLocalClient(tls); new Thread(tl1).start(); new Thread(tl2).start(); } } class ThreadLocalSeq { //通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值 private static ThreadLocal<String> state = new ThreadLocal<String>() { public String initialValue() { return ""; } }; //获取下一个序列值 public String getNextState() { state.set(state.get() + "-->|"); return state.get(); } public void setState(String st){ state.set(st); } } class ThreadStringSeq { //通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值 private static String state = ""; //获取下一个序列值 public String getNextState() { state = state + "-->|"; return state; } public void setState(String st){ state = st; } } class ThreadLocalClient implements Runnable { private ThreadLocalSeq sn; public ThreadLocalClient(ThreadLocalSeq sn) { super(); this.sn = sn; } public void run() { for (int i = 0; i < 3; i++) { //获取线程状态 System.out.println("ThreadLocalClient:" + Thread.currentThread().getName() + " sn:" + sn.getNextState()); } } } class ThreadStringClient implements Runnable { private ThreadStringSeq sn; public ThreadStringClient(ThreadStringSeq sn) { super(); this.sn = sn; } public void run() { for (int i = 0; i < 3; i++) { //获取线程状态 System.out.println("ThreadStringClient:" + Thread.currentThread().getName() + " sn:" + sn.getNextState()); } } }