ThreadLocal讲解

发表时间:2017-09-07 16:38:38 浏览量( 19 ) 留言数( 0 )

学习目标:

1、了解ThreadLocal的原理

2、了解InheritableThreadLocal的原理

3、能在程序中灵活的使用ThreadLocal和InheritableThreadLocal


学习过程:

一、ThreadLocal的入门

    当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。每个Thread Local 的实例代表了一个线程局部变量,它为每一条访问线程提供了单独的存储槽( storage slot )。你可以把它想象成具有多个槽的变量,然后每条线程可以在同一个变量中存储不同的值。并且,每条线程都只能看到自己的值,而不会意识到其他线程在这个变量中也有自己的值。Thread Local 被声明成泛型的Threadlocal<T>, 这里的T标识了存储在该变量中值的类型。

   ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

1、void set(Object value)设置当前线程的线程局部变量的值。

2、public Object get()该方法返回当前线程所对应的线程局部变量。

3、public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。

4、protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

   在JDK5.0以后的版本,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal<T>。API方法也相应进行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()。

看一下下面这个例子,虽然我们使用的是同一个ThreadLocal对象,但是我们在子线程中修改了ThreadLocal的值,但是主线程的值不会有任何影响的:

public class ThreadlocalDemo {
	private static volatile ThreadLocal<String> userID = new ThreadLocal<String>();

	public static void main(String[] args) throws InterruptedException {
		Runnable runnable = () -> {
			
			System.out.println("userId:"+userID.get());
			
			userID.set("设置为其他的值");
			
			System.out.println("其他线程的值:"+userID.get());
			
		};
		
	
		
		
		userID.set("liubao");//主线程设置值了,但是对其他线程不会有任何影响的。
		
		Thread thread1=new Thread(runnable);
		
		Thread thread2=new Thread(runnable);
		
		thread1.start();
		thread2.start();
		
		Thread.sleep(1000);
		
		System.out.println("主线程的值:"+userID.get());
		
		
	}
}


二、值从父线程传递给字线程

   有时候你或许想要把值从父线程( 一个创建其他线程的线程)传给子线程(被创建的线程),那么借助InheritableThreadLocal就可以完成这项任务。InheritableThreadLocal是ThreadLocal 的子类。

示例如下:

public class InheritableThreadLocalDemo {

	private static volatile InheritableThreadLocal<String> userID = new InheritableThreadLocal<String>();

	public static void main(String[] args) throws InterruptedException {
		Runnable runnable = () -> {

			userID.set("hello");

			Runnable child = () -> {
               System.out.println("获得父亲的"+userID.get());
			};
			
			Thread thread=new Thread(child);
			thread.start();
			
		};
		Thread thread=new Thread(runnable);
		thread.start();
		
	}

}