ThreadLocal

目录

什么是ThreadLocal

 ThreadLocalMap内部结构

为什么Entry对象的key是ThreadLocal对象

子线程如何共享到父线程的数据

 ThreadLocal如何避免内存泄漏


什么是ThreadLocal

ThreadLocal 可以理解为线程的口袋,口袋中存放当前线程有关的数据。

ThreadLocal 被称为线程局部变量,用于在线程中保存数据。由于在 ThreadLocal 中保存的数据仅属于当前线程,所以该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。

ThreadLocal_第1张图片 

ThreadLocal利用线程中的ThreadLocalMap来存储数据。

 

一般都会将ThreadLocal声明成一个静态字段,同时初始化

public class Demo01 {
	public static ThreadLocal threadLocal = new ThreadLocal();

	public static void main(String[] args) {
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				threadLocal.set("卧龙");
				show();
				Sample.dosth();
			}
		}, "线程1");

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				threadLocal.set("凤雏");
				show();
				Sample.dosth();
			}
		}, "线程2");

		t1.start();
		t2.start();

	}

	public static void show() {
		String show = threadLocal.get();
		System.out.println(Thread.currentThread().getName() + "分派" + show);
	}
}

class Sample {
	public static void dosth() {
		String show = Demo01.threadLocal.get();
		System.out.println(Thread.currentThread().getName() + "分派" + show);
	}
}

ThreadLocal_第2张图片

 

 ThreadLocalMap内部结构

ThreadLocal_第3张图片

ThreadLocalMap 内部数据结构是一个 Entry 类型的数组。每个 Entry 对象的 key 为 ThreadLocal 对象, value 为存储的数据。 

为什么Entry对象的key是ThreadLocal对象

如果我们用Thread对象作为key就会出现下图这种情况,一个key对应多个ThreadLocal:

ThreadLocal_第4张图片 

如果我们用ThreadLocal作为key就可以避免了上面的情况。ThreadLocal_第5张图片

 

虽然不同的线程之间threadlocal这个key值是一样,但是不同的线程所拥有的ThreadLocalMap是独一无二的,也就是不同的线程间同一个ThreadLocal(key)对应存储的值(value)不一样,从而到达了线程间变量隔离的目的,但是在同一个线程中这个value变量地址是一样的。

子线程如何共享到父线程的数据

使用 InheritableThreadLocal ,它是 JDK 自带的类,继承了 ThreadLocal类

ThreadLocal_第6张图片

ThreadLocal_第7张图片 

 ThreadLocal如何避免内存泄漏

使用完毕后,在 finally 调用 ThreadLocal 对象的 remove() 方法。

remove() 方法中会把 Entry 中的 key 和 value 都设置成 null ,这样就能被 GC 及时回收,无需触 发额外的清理机制,所以它能解决内存泄露问题

public class Demo02 {
	public static void main(String[] args) {
		ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS,
				new LinkedBlockingDeque());
		String[] roleArray = { "董卓", "曹操", "吕布", "关羽" };
		for (String role : roleArray) {
			poolExecutor.submit(new Runnable() {

				@Override
				public void run() {
					try {
						Demo01.show();
						Demo01.threadLocal.set(role);
						Demo01.show();
						Sample.dosth();
					} finally {
						Demo01.threadLocal.remove();
					}
				}
			});
		}
		poolExecutor.shutdown();

	}
}

ThreadLocal_第8张图片

 

 

你可能感兴趣的:(java,jvm,开发语言)