ThreadLocal 直译过来是 '本地线程',这个理解是不正确的。来看一个案例。
1.0 案例
先是一个接口
public interface Sequence { int getNumber(); }
实现类
public class SequenceA implements Sequence{ static int i = 0; public int getNumber() { return i++; } public static void main(String[] args){ SequenceA sequenceA = new SequenceA(); new MyThread(sequenceA).start(); new MyThread(sequenceA).start(); new MyThread(sequenceA).start(); } }
//线程类
public class MyThread extends Thread { private Sequence sequence; public MyThread(Sequence sequence){ this.sequence = sequence; } public void run() { for(int i=0;i<4;i++){ System.out.println(Thread.currentThread().getName()+"--"+sequence.getNumber()); } } }
运行结果
Thread-0--0
Thread-0--1
Thread-0--2
Thread-0--3
Thread-1--4
Thread-1--5
Thread-1--6
Thread-1--7
Thread-2--8
Thread-2--9
Thread-2--10
Thread-2--11
Process finished with exit code 0
因为
static int i = 0;
是静态的 是所有线程所共享的,所以会出现以上结果,那么我希望每个线程都有独立的 i 呢?
这时候ThreadLocal 派上用场了,
稍微改造了一下
public class SequenceA implements Sequence{ private static ThreadLocal<Integer> contaner = new ThreadLocal<Integer>(){ @Override protected Integer initialValue() { return 0; } }; public int getNumber(){ contaner.set(contaner.get()+1); return contaner.get(); } public static void main(String[] args){ SequenceA sequenceA = new SequenceA(); new MyThread(sequenceA).start(); new MyThread(sequenceA).start(); new MyThread(sequenceA).start(); } }
输出结果:
Thread-0--1
Thread-0--2
Thread-0--3
Thread-0--4
Thread-1--1
Thread-1--2
Thread-1--3
Thread-1--4
Thread-2--1
Thread-2--2
Thread-2--3
Thread-2--4
这才是我要的结果嘛,可是为什么 明明是 static的变量 却 每个线程都有了一份,,其实ThreadLocal其实相当于一个容器,它为每个线程 保存了 一个副本
那么 我们有必要来了解下ThreadLocal是怎么实现的 还有为什么我们要实现
它的 initialValue 方法
protected T initialValue() { return null; }
这是它的源码 方式是protected 那么 它就是提示我们去 现实它,
以下是它的源码 可以看出来 它里面封装了 一个Map 容器 来实现
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
有兴趣可以看看它的源码