package hxy.bytecode.thread.threadlocal;
public class ThreadLocalDemo {
static class ThreadA implements Runnable {
private ThreadLocal<String> threadLocal;
public ThreadA(ThreadLocal<String> threadLocal) {
this.threadLocal = threadLocal;
}
@Override
public void run() {
threadLocal.set("A");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadA " + threadLocal.get() + "\thashCode:" + threadLocal.hashCode());
}
}
static class ThreadB implements Runnable {
private ThreadLocal<String> threadLocal;
public ThreadB(ThreadLocal<String> threadLocal) {
this.threadLocal = threadLocal;
}
@Override
public void run() {
threadLocal.set("B");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("ThreadB " + threadLocal.get() + "\thashCode:" + threadLocal.hashCode());
}
}
public static void main(String[] args) {
ThreadLocal<String> threadLocal = new ThreadLocal<>();
threadLocal.set("测试");
// 上面新建了一个实例,下面传入多个线程,但是每个线程都复制了一个副本
new Thread(new ThreadA(threadLocal)).start();
new Thread(new ThreadB(threadLocal)).start();
new Thread(new ThreadB(threadLocal)).start();
System.out.println(Thread.currentThread().getName() + threadLocal.get() + "\thashCode:" + threadLocal.hashCode());
}
}
上面代码可以看出来,所有线程的对象应该都是使用了main方法新建的ThreadLocal的实例,但是传入到各个线程之后竟然全部不一样了。相当于每个线程都拥有了实例的副本,且各不相关,特殊之处就在本来就是一个对象,但是赋值到各个线程之后,竟然不是原来的。从下面打印的hashCode发现,各个线程接受的实例确实是main方法创建的同一个,但是为啥效果却不一样了。
image.png进入ThreadLocal的set方法一探究竟。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocal.ThreadLocalMap map = this.getMap(t);
if (map != null) {
map.set(this, value);
} else {
this.createMap(t, value);
}
}
从上面可以看出来端倪了。系统维护了个全局变量的map,可以依据线程放对象线程的map值,然后再依据线程去取出该线程的map对象就好了。
网友评论